Blade Template Engine

trong Laravel

Giới thiệu

Blade là "framework layout" đi kèm với Laravel

*Note: Tất cả code blade được biên dịch về thành code PHP thuần.

Template Inheritance

Kế thừa template

Template Inheritance

1. Định nghĩa "Master Layout"

<!-- Stored in resources/views/layouts/app.blade.php -->

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

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

*Master Layout: Hầu như tất cả các website đều có một "khung layout" dùng chung cho tất cả các trang.

Template Inheritance

2. Kế thừa master layout

<!-- Stored in resources/views/child.blade.php -->

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

*Views con extends view cha và định nghĩa các @section ở biên trong.  Ở view cha sẽ hiện nó ra ở trong chỗ @yield

Components & Slots

Components & Slots

Components và slots giống @section và layouts, tuy nhiên nhiều người thấy cái này "dễ hiểu" hơn.

* ví dụ về  component "alert" có thể tái sử dụng được trong toàn app.

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

Components & Slots

Giờ để sử dụng component này, chúng ta sử dụng "chỉ dẫn" (directive) @component

@component('alert')
    <strong>Whoops!</strong> Something went wrong!
@endcomponent

Components & Slots

Load component đầu tiên trong mảng component sử dụng @componentFirst

@componentFirst(['custom.alert', 'alert'])
    <strong>Whoops!</strong> Something went wrong!
@endcomponent

Components & Slots

Định nghĩa nhiều slots cho các component và chuẩn bị cho việc inject biến $title vào.

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

Components & Slots

Định nghĩa biến $title trong @slot và nội dung bên ngoài @slot sẽ được nhét vào biến $slot.

@component('alert')
    @slot('title')
        Forbidden
    @endslot

    You are not allowed to access this resource!
@endcomponent

Components & Slots

Truyền thêm giá trị vào cho component, sau đó lấy nội dung thông qua biến chính là "key".

@component('alert', ['foo' => 'bar'])
    ...
@endcomponent

Passing Additional Data To Components

Components & Slots

Đặt tên lại cho component để dễ gọi hơn.

use Illuminate\Support\Facades\Blade;

Blade::component('components.alert', 'alert');

Aliasing Components

@alert(['type' => 'danger'])
    You are not allowed to access this resource!
@endalert
@alert
    You are not allowed to access this resource!
@endalert

Displaying Data

Hiển thị dữ liệu

Displaying Data

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

* Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.

The current UNIX timestamp is {{ time() }}.

Displaying Data

Hello, {!! $name !!}.
<script>
    var app = <?php echo json_encode($array); ?>;
</script>
<script>
    var app = @json($array);

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

Displaying Unescaped Data

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

* @json cần được đặt trong nháy đơn ''.

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

Displaying Data

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::withoutDoubleEncoding();
    }
}

HTML Entity Encoding

Displaying Data

<h1>Laravel</h1>

Hello, @{{ name }}.

Blade & JavaScript Frameworks

@verbatim
    <div class="container">
        Hello, {{ name }}.
    </div>
@endverbatim

The @verbatim Directive

Control Structures

Control Structures

If Statements

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif
@unless (Auth::check())
    You are not signed in.
@endunless
@isset($records)
    // $records is defined and is not null...
@endisset

@empty($records)
    // $records is "empty"...
@endempty

Control Structures

Authentication Directives

@auth
    // The user is authenticated...
@endauth

@guest
    // The user is not authenticated...
@endguest
@auth('admin')
    // The user is authenticated...
@endauth

@guest('admin')
    // The user is not authenticated...
@endguest

Control Structures

Section Directives

@hasSection('navigation')
    <div class="pull-right">
        @yield('navigation')
    </div>

    <div class="clearfix"></div>
@endif

Control Structures

Switch Statements

@switch($i)
    @case(1)
        First case...
        @break

    @case(2)
        Second case...
        @break

    @default
        Default case...
@endswitch

Control Structures

Loops

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile

Control Structures

Loops

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

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

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

* Sử dụng biến $loop để lấy thêm thông tin về vòng lặp, ví dụ như index của lần lặp hiện tại.

Control Structures

Loops

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

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

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

* Có thể viết điều kiện và chỉ dẫn (directive) trong cùng 1 dòng

Control Structures

The Loop Variable

@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif

    @if ($loop->last)
        This is the last iteration.
    @endif

    <p>This is user {{ $user->id }}</p>
@endforeach
@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

Control Structures

The Loop Variable

* Biến $loop cung cấp thêm rất nhiều thông tin hữu ích.

Property Description
$loop->index The index of the current loop iteration (starts at 0).
$loop->iteration The current loop iteration (starts at 1).
$loop->remaining The iterations remaining in the loop.
$loop->count The total number of items in the array being iterated.
$loop->first Whether this is the first iteration through the loop.
$loop->last Whether this is the last iteration through the loop.
$loop->even Whether this is an even iteration through the loop.
$loop->odd Whether this is an odd iteration through the loop.
$loop->depth The nesting level of the current loop.
$loop->parent When in a nested loop, the parent's loop variable.

Control Structures

Comments

{{-- This comment will not be present in the rendered HTML --}}

Control Structures

PHP

@php
    //
@endphp

Thêm code PHP thuần ở trong template

Forms

Forms

CSRF Field

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

    ...
</form>

Forms

Method Field

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

    ...
</form>

Forms

Validation Errors

<!-- /resources/views/post/create.blade.php -->

<label for="title">Post Title</label>

<input id="title" type="text" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

Including Sub-Views

Including Sub-Views

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

    <form>
        <!-- Form Contents -->
    </form>
</div>
@include('view.name', ['some' => 'data'])
@includeIf('view.name', ['some' => 'data'])
@includeWhen($boolean, 'view.name', ['some' => 'data'])
@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])

Including Sub-Views

<input type="{{ $type ?? 'text' }}">
use Illuminate\Support\Facades\Blade;

Blade::include('includes.input', 'input');
@input(['type' => 'email'])

Aliasing Includes

* Nếu file blade của mình ở trong thư mục con, mình có thể đặt tên lại để gọi cho "ngắn" hơn. Ví dụ như file .blade để ở resources/views/includes/input.blade.php, mình có thể đặt tên từ includes.input thành input.

Sau đó gọi như là một Blade directive thành @input.

Including Sub-Views

@each('view.name', $jobs, 'job')
@each('view.name', $jobs, 'job', 'view.empty')

Rendering Views For Collections

Vừa lặp vừa include. Tham số là:

1. Tên view

2. Mảng dữ liệu

3. Tên biến đại diện cho mỗi lần lặp

4. View hiển thị nếu mảng dữ liệu rỗng

Stacks

Stacks

@push('scripts')
    <script src="/example.js"></script>
@endpush
<head>
    <!-- Head Contents -->

    @stack('scripts')
</head>
@push('scripts')
    This will be second...
@endpush

// Later...

@prepend('scripts')
    This will be first...
@endprepend

Service Injection

@inject('metrics', 'App\Services\MetricsService')

<div>
    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

Extending

Blade

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }
}

Custom If Statements

use Illuminate\Support\Facades\Blade;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Blade::if('env', function ($environment) {
        return app()->environment($environment);
    });
}

Extending

Blade

@env('local')
    // The application is in the local environment...
@elseenv('testing')
    // The application is in the testing environment...
@else
    // The application is not in the local or testing environment...
@endenv

Let's code it !

Made with Slides.com