Blade

Blade je jednoduchý šablonovací nástroj od Laravelu. Narozdíl od jiných populárních šablonovacích systémů Blade umožňuje používat v pohledech i klasické PHP kódy. Ve výsledku se totiž Blade pohledy vždy zkompikují do čistého PHP a zakešují do té doby, než jsou změněny. Blade pohledy mají koncovku .blade.php a ve výchozím nastavení je najdeme v adresáři resources/views.

Dědičnost

Jednou z hlavních výhod při používání Blade jsou dědičnost šablon. Nejlepší to bude ukázat na příkladu. Drtivá většina stránek má layout vždy stejný, tedy například hlavičku, menu a patičku. Jediné co se mění, je samotný obsah. Jako první si tedy definujeme "hlavní" layout:

<!-- Layout ulozime do resources/views/layouts/app.blade.php -->

<html>
 <head>
     <title>Blog - @yield('title')</title>
 </head>
 <body>
     @section('sidebar')
        Toto je boční menu.
     @show

     <div class="container">
         @yield('content')
     </div>
 </body>
</html>

Jak můžeme vidět, většina kódu je klasické HTML. Nicméně si všimněte direktiv @yield a @section. Direktiva @section, jak už název napovídá, definuje sekci kde bude obsah, zatímco direktiva @yield slouží pro zobrazení obsahu dané sekce.

Tímto jsme si definovali základní layout a můžeme se vrhnout na další stránky, které budou tento layout dědit.

Rozšíření layoutu

Když definujeme potomka, tak jako první použijeme direktivu @extends pro specifikování z jakého layoutu chceme dědit. Dále můžeme pomocí direktivy @section vložit potřebný kód do obsahu rodiče. Kde se má tento obsah zobrazit jsme si definovali v app.blade.php direktivou @yield. Může to znít trochu složitě, ale ukážeme si to na příkladě, kde se to dá lépe pochopit:

<!-- Ulozene v resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Název stránky')

@section('sidebar')
 @parent

 <p>Tato část se připojí k hlavnímu sidebaru.</p>
@endsection

@section('content')
 <p>Toto je hlavní obsah.</p>
@endsection

V Blade se používá vazba @yield a @section. @yield definuje, že zde bude dynamický obsah a @section zajišťuje samotný obsah sekce. To je příklad sekce title a content. Narozdíl od toho sekce sidebar využívá direktivy @parent, protože nechce původní (rodičovský) kód přepsat, ale pouze ho doplnit k tomu, co už v sekci existuje.

Pokud bychom si chtěli stránku rovnou zobrazit, definujme si routu například /blade:

Route::get('blade', function () {
 return view('child');
});

Všimněte si, že jsme vrátili rovnou konečný Blade pohled, tedy child.blade.php. Rodiče není potřeba nijak řešit, protože potomek se sám stará o zavolání rodiče (direktiva @extends).

Zobrazení dat

Pokud nechceme mít pouze statické stránky, tak potřebujeme předávat do šablon i proměnné. To zajistíme tak, že při volání helperu view() jako druhý parametr (první parametr je název šablony) uvedeme pole s klíči a proměnnými:

Route::get('greeting', function () {
    return view('welcome', ['name' => 'Hugo']);
});

V samotné šabloně pak proměnnou name s hodnotou Hugo zobrazíme pomocí složených závorek:

Ahoj, tady {{ $name }}

Je potřeba zmínit, že veškerý obsah ve složených závorkách prochází PHP funkcí htmlspecialchars(), která zabraňuje XSS útokům. Kromě toho nás nic nelimituje, jaký kód do složených závorek dáme. Můžeme dokonce i bez problémů volat nativní PHP funkce:

Aktuální UNIX časová známka je {{ time() }}.

Zobrazení neošetřených dat

Jak už jsem zmínil, veškerý obsah prochází kvůli ochraně funkcí htmlspecialchars(). Pokud si jsme jistí jaký obsah se zde bude vkládat a máme pro to dobrý důvod, můžeme tuto ochranu obejít použitím této syntaxe:

Ahoj, tady {!! $name !!}

Zobrazení JSON

Často se stává, že potřebujeme do šablony vložit do javascript proměnné data z backendu. Běžně bychom to museli udělat například takto:

<script>
    var app = <?php echo json_encode($array); ?>;
</script>

Blade nám v tomto vychází vstříc a namísto toho můžeme využít direktivy @json:

<script>
    var app = @json($array);
</script>

To se může především hodit při definování hodnot ve Vue komponentách nebo v data-* atributech:

<example-component :some-prop='@json($array)'></example-component>

Operace s daty

Kromě dědičnosti a zobrazení dat umožňuje Blade také klasické operace s daty, jako jsou podmínky nebo cykly. Laravel se nám v tomto snaží jít co nejvíce naproti a umožňuje nám práci s nimi velmi jednoduše.

Podmínky

Direktivy pro podmínky jsou @if, @elseif, @else a @endif. Tyto direktivy fungují úplně stejné, jako bychom použili klasické PHP:

@if (count($records) === 1)
    Pouze jeden záznam
@elseif (count($records) > 1)
    Více záznamů
@else
    Žádný záznam
@endif

Pro zjednodušení Blade také nabízí direktivu @unless, která prakticky znamená if($variable === false):

@unless (Auth::check())
    Nejste přihlášeni.
@endunless

Kromě těchto možností je také možné použít direktiv @isset a @empty:

@isset($records)
    // $records je definovan a neni nulovy
@endisset

@empty($records)
    // $records je "prazdny"
@endempty

Switch

Direktivy pro switch jsou @switch, @case, @break, @default a @endswitch. Ty opět fungují stejně jako jejich klasické PHP protějšky:

@switch($i)
    @case(1)
        První nález
        @break

    @case(2)
        Druhý nález
        @break

    @default
        Nic se nenašlo
@endswitch

Cykly

Pro procházení dat můžeme v Blade využít cykly, které běžně využíváme v PHP:

@for ($i = 0; $i < 10; $i++)
    Aktuální hodnota je {{ $i }}
@endfor

@foreach ($users as $user)
    <p>Tento uživatel má ID {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>Žádní uživatelé</p>
@endforelse

@while (true)
    <p>Nekonečný cyklus.</p>
@endwhile

Kromě procházení dat můžeme také cyklus ukončit nebo přeskočit aktuální iteraci:

@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif

    <li>{{ $user->name }}</li>

    @if ($user->number == 5)
        @break
    @endif
@endforeach

Nebo použít zkrácenou verzi:

@foreach ($users as $user)
    @continue($user->type == 1)

    <li>{{ $user->name }}</li>

    @break($user->number == 5)
@endforeach

Proměnná v iteraci

Když probíhá cyklus, tak Laravel automaticky do iterace vkládá i proměnnou $loop. Tato proměnná obsahuje užitečné informace o aktuální iteraci:

@foreach ($users as $user)
    @if ($loop->first)
        Toto je první iterace a první uživatel je {{ $uesr->name }}
    @endif

    @if ($loop->last)
        Toto je poslední iterace a poslední uživatel je {{ $uesr->name }}
    @endif

    <p>Uživatel má ID {{ $user->id }}</p>
@endforeach

Pokud bychom měli víceúrovňový cyklus, pak se můžeme dostat i k rodiči:

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            Toto je první iterace rodičovského cyklu
        @endif
    @endforeach
@endforeach

Kromě těchto metod proměnná $loop obsahuje i jiné velmi užitečné metody:

Metoda Popis
$loop->index Index aktuální iterace (začíná od 0)
$loop->iteration Aktuální iterace (začíná od 1)
$loop->remaining Zbývající iterace v cyklu
$loop->count Celkový počet záznamů v poli, které se bude procházet
$loop->first Jestli je tato iterace první v cyklu
$loop->last Jestli je tato iterace poslední v cyklu
$loop->even Jestli je tato iterace sudá v cyklu
$loop->odd Jestli je tato iterace lichá v cyklu
$loop->depth Hloubka aktuální iterace
$loop->parent Rodičovská proměnná $loop pokud se jedná o zanořený cyklus

Komentáře

Blade také umožňují definovat komentáře. Je důležité připomenout, že narozdíl od HTML komentářů, Blade komentáře se ve výsledném HTML nevrací, ve zdrojovém kódu je tak neuvidíte (namísto toho je jen prázdné místo):

{{-- Tento komentar nebude ve vyslednem vyrenderovanem HTML --}}

PHP

V některých situacích je potřeba vkládat PHP kód do šablon. K tomu můžeme využít direktivu @php, která v šabloně vykoná daný PHP kód:

@php
    //
@endphp

Formulář

CSRF pole

Pokaždé když definujeme HTML formulář, měli bychom vkládat i skryté CSRF pole s tokenem, takže zabráníme CSRF útoku a požadavek zároveň projde přes middleware (defaultně bez tohoto tokenu se požadavek nevykoná a vyhodí to chybu 419). Abychom nemuseli toto skryté pole psát ručně, můžeme využít Blade direktivu @csrf:

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

    ...
</form>

Pole s typem requestu

Protože HTML formuláře nedokážou vytvářet požadavky typu PUT, PATCH nebo DELETE, pro jejich odeslání je potřeba přidat skryté pole _method s HTTP typem požadavku. Blade direktiva @method toto pole vytvoří za nás:

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form>

Přidání dalších pohledů

Pokud bychom do šablony potřebovali vložit další šablonu, například pro separovaní vetší části kódu kvůli čitelnosti nebo znovupoužitelnosti, můžeme použít direktivu @include. Všechny proměnné, které jsou dostupné pro rodiče, budou také dostupné pro vkládnou šablonu:

<div>
    @include('shared.errors')

    <form>
        <!-- Obsah formulare -->
    </form>
</div>

Kromě toho, že jsou předávány všechny rodičovské proměnné, můžeme do přidávané šablony také přidat další extra data:

@include('view.name', ['some' => 'data'])

Pokud chcete vložit šablonu pouze na základě určité podmínky, pak to lze udělat jednoduše pomocí direktivy @includeWhen:

@includeWhen($boolean, 'view.name', ['some' => 'data'])