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 !

Blade Template Engine trong Laravel

By dannguyencoder

Blade Template Engine trong Laravel

Những tính năng mà Blade Engine cung cấp cho chúng ta để cắt layout tiện hơn so với PHP thuần.

  • 338