PHP týden Předvánoční slevová akce
Pouze tento týden sleva až 80 % na PHP e-learning!
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde

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

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, První aplikace v Laravel, jsme rozpracovali jednoduchou kalkulačku v Laravel. Vytvořili jsme si model, kontroler a pohled. Je na čase tyto části aplikace propojit.

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

/*
|--------------------------------------------------------------------------
| 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', '[email protected]');

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

Kalkulačka v PHP frameworku Laravel

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', '[email protected]');
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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:60,1',
        'bindings',
    ],
];

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

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

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é.

To je pro tuto lekci vše. Dokončili jsme kalkulačku a v příští lekci, Jednoduchý redakční systém v Laravel - Struktura projektu, se vrhneme na nový projekt, kde se podíváme na některé části frameworku již více do hloubky.


 

Stáhnout

Staženo 56x (13.59 MB)
Aplikace je včetně zdrojových kódů v jazyce php

 

 

Článek pro vás napsal Jan Lupčík
Avatar
Jak se ti líbí článek?
7 hlasů
Autor se primárně věnuje vývoji webových stránek a aplikacích v PHP (speciálně ve frameworku Laravel) a je jedním z vývojářů komunitního módu TruckersMP.
Předchozí článek
První aplikace v Laravel
Všechny články v sekci
Laravel framework pro PHP
Miniatura
Následující článek
Jednoduchý redakční systém v Laravel - Struktura projektu
Aktivity (8)

 

 

Komentáře

Avatar
Josef Prause
Člen
Avatar
Josef Prause:3. června 12:54

Celou lekci Kalkulačka jsem prošel a aplikoval. Avšak po odeslání Spočítej výsledek dostávám chybu:
Class 'App\Http\Con­trollers\Rule' not found

Kde dělám chybu? Děkuji

 
Odpovědět
3. června 12:54
Avatar
Jan Lupčík
Šéfredaktor
Avatar
Odpovídá na Josef Prause
Jan Lupčík:3. června 16:58

Ahoj,
děkuji za upozornění na chybu. Jak stále používám PhpStorm, jenž mi importuje třídy sám, nezmínil jsem, že nad název třídy v kontroleru musíš umístit:

use Illuminate\Validation\Rule;

Co nejdříve to během následujících dnů také doplním do článku. :)

Odpovědět
3. června 16:58
TruckersMP vývojář
Avatar
Josef Prause
Člen
Avatar
Josef Prause:3. června 18:50

Děkuji, to pomohlo.
Ale teď náhle po zadání php artisan serve
dostávám chybu:
Method Illuminate\Rou­ting\Route::get does not exist.
aniž jsem cokoliv měnil.

 
Odpovědět
3. června 18:50
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Lupčík
Šéfredaktor
Avatar
Odpovídá na Josef Prause
Jan Lupčík:4. června 15:43

Ahoj,
v jakém souboru se daná chyba vyskytuje? Mohl by si případně přiložit chybovou hlášku a kód daného souboru?
Taky bys mohl ještě na začátek souboru routes/web.php vložit následující řádek:

use Illuminate\Support\Facades\Route;

Zdá se, že se to snaží použít nějaký jiný soubor, než by mělo.

Odpovědět
4. června 15:43
TruckersMP vývojář
Avatar
Josef Prause
Člen
Avatar
Josef Prause:4. června 18:31

Nazdar,
omlouvám se, ale to už nebudeme zkoumat. Přeinstaloval jsem projekt first-application a vše funguje jak má. Možná jsem omylem zasáhl nesprávně do nějakého souboru.
Děkuji za odpovědi a za celý článek o vývoji aplikace, hodně jsem se dozvěděl. Také při tom zkouším PhpStorm, dosud používám Netbeans.

 
Odpovědět
4. června 18:31
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.