IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Dokončení kalkulačky v Laravel

V minulé lekci, První aplikace v Laravel, jsme rozpracovali jednoduchou kalkulačku v Laravel. Vytvořili jsme si model, kontroler a pohled.

V dnešním kurzu si propojíme jednotlivé části naší aplikace a podíváme se také na validaci formuláře.

Routování

Abychom se mohli podívat, jak naše aplikace aktuálně vypadá, potřebujeme ke kontroleru přistoupit přes nějakou URL adresu. Na to nám slouží routování, jeho proces jsme si popsali v úvodní lekci. Pojďme si nyní definovat naší první routu, která kontroler napojí na nějakou adresu.

Definované routy pro náš web najdeme v souboru routes/web.php. Tento soubor je od instalace nezměněný:

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Zatím máme jako výchozí definovanou pouze jednu routu. Jedná se o zobrazení hlavní stránky přes GET (statická metoda get() třídy Route) a zpracovává se anonymní funkcí. Takto můžeme zpracovávat jakoukoliv routu. My jsme si již vytvořili kontroler a ten také teď využijeme. Na konec souboru přidáme vlastní definování GET routy, kde místo vytvoření funkce odkážeme na akci našeho kontroleru:

Route::get('calculator', [CalculatorController::class, 'index']);

Nesmíme zapomenout importovat třídu kontroleru:

use App\Http\Controllers\CalculatorController;

Nyní pokud zadáme do URL naší aplikace /calculator, uvidíme následující kalkulačku:

Kalkulačka v PHP frameworku Laravel - Laravel framework pro PHP

Je na čase si kalkulačku zprovoznit. Vrátíme se tedy ke kontroleru, kde zpracujeme POST formulář.

Zpracování odeslání formuláře

V našem kontroleru CalculatorController si definujeme novou metodu, kterou pojmenujeme calculate(). Ta nám bude přijímat požadavky z formuláře a následně zobrazovat výsledek:

/**
 * Zpracuj požadavek formuláře a zobraz výsledek spolu s formulářem kalkulačky.
 *
 * @param  Calculator $calculator
 * @return View
 */
public function calculate(Calculator $calculator): View
{
    $a = request()->input('a');
    $b = request()->input('b');
    $operation = request()->input('operation');
    $result = $calculator->calculate($operation, $a, $b);

    return view('calculator', [
        'operations' => $calculator->getOperations(),
        'result' => $result,
        'a' => $a,
        'b' => $b,
    ]);
}

Stejně jako u zobrazení kalkulačky, i zde získáváme instanci modelu Calculator do proměnné $calculator přes dependency injection. Ta zajímavá část ale začíná až uvnitř metody.

Pro získání odeslaných hodnot používáme metodu input() Laravel třídy Request, kterou získáme pomocí helper funkce request(). Následně získané hodnoty použijeme pro naší metodu calculate(), kterou jsme si definovali v minulé lekci v modelu Calculator. A dále zobrazíme pohled calculator.blade.php přes helper funkci view() stejně jako v metodě index(). Pohledu opět předáme dostupné operace kalkulačky, navrch jsme však přidali výsledek a odeslaná čísla přes formulář, abychom je opět mohli zobrazit.

Následně si vytvoříme novou routu v routovacím souboru webu routes/web.php stejně jako jsme to udělali výše. Nyní si však přidáme POST akci:

Route::post('calculator', [CalculatorController::class, 'calculate']);

Všimli jste si, že jsme definovali dvě routy se stejným názvem, ale jedna je GET a druhá POST? I přesto bude naše kalkulačka bez problému fungovat. Framework si sám zjistí, o jaký požadavek se jedná, a následně zavolá danou metodu kontroleru:

  • Pro zobrazení (GET) se tedy zavolá metoda index() v kontroleru CalculatorController.
  • Po odeslání formuláře (POST) se zavolá calculate() ve stejném kontroleru.

Pokud však zkusíme nyní formulář odeslat, dostaneme chybu 419 i přesto, že vše by mělo fungovat. Nebo ne?

CSRF token

Laravel chrání naše požadavky proti CSRF útoku. Tato ochrana je spuštěna pro všechny akce, které nejsou čtecí (všechny krom GET). A co že je vlastně ten CSRF útok?

Představte si situaci, kdy jsme vytvořili nějaký populární blog a někdo by vytvořil úplně jinou stránku, kam by dal formulář vybízející ke vkládání vulgárních příspěvků. Tento formulář by ovšem nenechal odesílat data na jeho stránku, nýbrž na náš blog. Nic netušící uživatelé by rázem psali příspěvky na náš blog, i když by se na této stránce vůbec nenacházeli a nevěděli, že tam něco posílají.

Musíme formulář tedy opatřit CSRF tokenem, pomocí kterého se ověřuje, že požadavek byl odeslán přes naší stránku a ne přes stránku cizí.

To se dělá pomocí Blade direktivy @csrf, která se přemění na {{ csrf_field() }} (tento delší zápis se používal ve starších verzích). Direktivou bude formuláři vygenerováno skryté pole s CSRF tokenem. Upravíme si tedy formulář v pohledu calculator.blade.php (ve složce resources/views):

<form method="POST" action="/calculator">
    @csrf

    Operace:

Pokud nyní zkusíme odeslat formulář, bude už vše fungovat tak, jak bychom si představovali.

CSRF ochrana pomocí middleware

CSRF ochrana je zajištěna jedním z middlewarů Laravel frameworku. To je vrstva, kterou se požadavek zpracuje ještě předtím, než se dostane ke kontroleru. Takovéto middlewary zpracovávající všechny akce najdeme definované v souboru app/Http/Kernel.php. Máme jich hned několik pro skupinu web:

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

Přes tyto všechny middlewary projde náš požadavek, než se dostane k metodě našeho kontroleru. Můžeme vidět, že dalšími z nich jsou například šifrování cookies a vytvoření relace (session). Pokud někdy budete chtít vytvářet svůj vlastní middleware, toto je přesně místo, kde ho budete přidávat. Následně tak bude aplikován pro všechny akce na vaší webové stránce.

Validace formuláře

Jako programátor musíme předpokládat, že ne vždy uživatel vyplní do políčka to, co po něm požadujeme. Pokud zkusíme zadat do políčka s číslem text, naše aplikace vyvolá chybu, protože model dokáže přijímat pouze celá čísla:

Chyba Laravel kalkulačky při předání textu - Laravel framework pro PHP

Tomu se můžeme vyhnout validací. Validační pravidla lze definovat v kontroleru přímo v metodě dané akce. My využijeme pouze pár pravidel, všechny lze najít v oficiální dokumentaci. V našem případě se jedná o to, že všechna políčka musí být vyplněná a že požadujeme pouze celá čísla. Také vybraná operace musí být podporovaná naším modelem. Upravíme si tedy metodu calculate() v našem kontroleru:

/**
 * Zpracuj požadavek formuláře a zobraz výsledek spolu s formulářem kalkulačky.
 *
 * @param  Calculator $calculator
 * @return View
 *
 * @throws ValidationException
 */
public function calculate(Calculator $calculator): View
{
    $this->validate(request(), [
        'a' => ['required', 'integer'],
        'b' => ['required', 'integer', 'not_in:0'],
        'operation' => [
            'required',
            Rule::in(array_keys($calculator->getOperations())),
        ],
    ]);

    $a = request()->input('a');

Začneme od anotace, kdy místo zpracování výjimky ValidationException ji předáme frameworku. Ten se o ní sám dokáže postarat, kdy uživatele přesměruje zpět i s chybami, kterých se dopustil.

Následně voláme metodu validate(), která je definovaná v třídě Controller a náš kontroler ji dědí. Té musíme předat instanci třídy Request, již lze získat opět přes helper funkci request(). Jako druhý parametr předáváme pole s nastavenými validačními pravidly. Ty mohou být definované pouze jako text. Pro jiné, jako například pravidlo in, je lepší použít třídu Rule. Také si všimněte, že jsme vyřešili problém pro dělení nulou, kdy druhé číslo nesmí být 0.

Myslím si, že další pravidla není třeba vysvětlovat, všechny jsou popsané v uvedené dokumentaci.

Pokud vaše prostředí nedokáže automaticky rozpoznat třídy z jiného jmenného prostoru, nezapomeňte si na začátek souboru třídy kontroleru přidat následující importy:

use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;

Vypsání chyb

Nyní už stačí jen vypsat chyby v našem pohledu, abychom informovali uživatele o omylech, kterých se dopustil. Chyby jsou obsažené v proměnné $errors, ta je automaticky předávaná všem pohledům. Takovýchto "nedefinovaných" proměnných je více, nám však stačí zatím pouze tato. Upravíme si tedy náš pohled a pod nadpis přidáme výpis chyb:

<h1>Kalkulačka</h1>

@if ($errors->any())
    <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif

<form method="POST" action="/calculator">

$errors je instance třídy ViewErrorBag. Pro zjištění, zda-li vůbec existují nějaké chybové hlášky, abychom nezobrazovali prázdný seznam, použijeme metodu any(). Všechny chybové hlášky poté získáme přes metodu all() a vypíšeme je. Pokud byste však chtěli získat chybovou hlášku pouze pro určité políčko, lze použít metodu first() a předat ji název políčka:

$errors->first('email')

Nám každopádně postačí i pouze seznam chyb :)

Pokud zkusíme zadat jako druhé číslo nulu a přes "Inspect element" (klávesa F12 v prohlížeči) vytvoříme neexistující operaci kalkulačky, dostaneme dvě chybové hlášky:

Chybové hlášky v PHP frameworku Laravel - Laravel framework pro PHP

Nyní máme plně fungující kalkulačku vytvořenou přes Laravel, na které jsme si ukázali naprosté základy tohoto PHP frameworku. Pokud vám není cokoliv jasné, stáhněte si projekt z přiloženého archivu a podívejte se na řešení. Můžete se též zeptat v diskuzi pod článkem, pokud-li čelíte nějakému problému. Každopádně s potřebnými znalostmi, které jsem uvedl v první lekci, by vše mělo být po chvilce jasné.

V následujícím kvízu, Kvíz - Výpis, routy a MVC v Laravel, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 260x (11.99 MB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
První aplikace v Laravel
Všechny články v sekci
Laravel framework pro PHP
Přeskočit článek
(nedoporučujeme)
Kvíz - Výpis, routy a MVC v Laravel
Článek pro vás napsal Jan Lupčík
Avatar
Uživatelské hodnocení:
41 hlasů
Autor se primárně věnuje vývoji webových stránek a aplikací v PHP (framework Laravel) a je jedním z herních vývojářů komunitní modifikace TruckersMP.
Aktivity