Skip to content

Blade Templates

Giới thiệu (Introduction)

Blade là templating engine đơn giản nhưng mạnh mẽ đi kèm Laravel. Khác với một số PHP templating engines, Blade không hạn chế bạn dùng PHP code trong templates. Tất cả Blade templates được biên dịch thành PHP thuần và cached cho đến khi thay đổi.

Blade template files sử dụng extension .blade.php và nằm trong thư mục resources/views.

Tăng sức mạnh Blade với Livewire

Muốn nâng Blade lên tầm cao mới? Xem Laravel Livewire — viết frontend components được hỗ trợ Blade, có khả năng tương đương SPA framework như React/Vue.

Hiển thị dữ liệu (Displaying Data)

Hiển thị biến bằng cú pháp "curly brace" :

blade
Hello, {{ $name }}.

Thời gian UNIX hiện tại: {{ time() }}.

Hiển thị Unescaped Data

Mặc định, Blade tự động dùng htmlspecialchars để ngăn XSS. Nếu không muốn escape:

blade
Hello, {!! $name !!}.

CẢNH BÁO

Hãy rất cẩn thận khi hiển thị nội dung do user cung cấp. Luôn dùng cú pháp double curly brace để ngăn XSS attacks.

Blade và JavaScript Frameworks

Nhiều JavaScript frameworks cũng dùng "curly braces". Dùng ký tự @ để báo Blade giữ nguyên:

blade
<h1>Laravel</h1>

Hello, @{{ name }}.

Directive @verbatim

Hiển thị biến JavaScript trên vùng lớn:

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

Blade Directives

If Statements

blade
@if (count($records) === 1)
    Có một record!
@elseif (count($records) > 1)
    Có nhiều records!
@else
    Không có records nào!
@endif

Blade cũng cung cấp các directives tiện lợi:

blade
@unless (Auth::check())
    Bạn chưa đăng nhập.
@endunless

@isset($records)
    // $records đã định nghĩa và không null...
@endisset

@empty($records)
    // $records là "empty"...
@endempty

Authentication Directives

blade
@auth
    // User đã authenticated...
@endauth

@guest
    // User chưa authenticated...
@endguest

Switch Statements

blade
@switch($i)
    @case(1)
        Giá trị đầu...
        @break

    @case(2)
        Giá trị thứ hai...
        @break

    @default
        Giá trị mặc định...
@endswitch

Loops

blade
@for ($i = 0; $i < 10; $i++)
    Giá trị hiện tại: {{ $i }}
@endfor

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

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>Không có users nào</p>
@endforelse

@while (true)
    <p>Lặp mãi mãi.</p>
@endwhile

Biến $loop

Bên trong loops, biến $loop cung cấp thông tin hữu ích:

PropertyMô tả
$loop->indexIndex hiện tại (bắt đầu từ 0)
$loop->iterationIteration hiện tại (bắt đầu từ 1)
$loop->remainingIterations còn lại
$loop->countTổng số items
$loop->firstCó phải iteration đầu tiên
$loop->lastCó phải iteration cuối cùng
$loop->evenCó phải iteration chẵn
$loop->oddCó phải iteration lẻ
$loop->depthMức lồng nhau
$loop->parentBiến $loop của loop cha

Conditional Classes & Styles

Directive @class biên dịch CSS class string có điều kiện:

blade
@php
    $isActive = false;
    $hasError = true;
@endphp

<span @class([
    'p-4',
    'font-bold' => $isActive,
    'text-gray-500' => ! $isActive,
    'bg-red' => $hasError,
])></span>

Include Subviews

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

    <form>
        <!-- Nội dung Form -->
    </form>
</div>

@includeIf('view.name', ['status' => 'complete'])
@includeWhen($boolean, 'view.name', ['status' => 'complete'])
@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])

Raw PHP

blade
@php
    $counter = 1;
@endphp

Comments

blade
{{-- Comment này sẽ không xuất hiện trong rendered HTML --}}

Components

Components và slots tương tự sections/layouts, nhưng workflow trực quan hơn, đặc biệt thích hợp cho component-based design.

Class-Based Components

bash
php artisan make:component Alert

Tạo component class trong app/View/Components và view template trong resources/views/components.

Rendering Components

blade
<x-alert/>
<x-alert type="error" :message="$message"/>

Truyền Data cho Components

Truyền qua HTML attributes. Primitive values dùng strings, PHP expressions dùng prefix ::

blade
<x-alert type="error" :message="$message"/>

Slots

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

<!-- Sử dụng -->
<x-alert>
    <strong>Thất bại!</strong> Có lỗi xảy ra.
</x-alert>

Named slots:

blade
<x-alert>
    <x-slot:title>
        Tiêu đề Alert
    </x-slot>

    Nội dung alert...
</x-alert>

Anonymous Components

Components chỉ có Blade template, không có class:

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

@props(['type' => 'info', 'message'])

<div {{ $attributes->merge(['class' => 'alert alert-'.$type]) }}>
    {{ $message }}
</div>

Building Layouts (Xây dựng Layouts)

Layouts dùng Components

blade
<!-- resources/views/components/layout.blade.php -->
<html>
    <head>
        <title>{{ $title ?? 'Ứng dụng của tôi' }}</title>
    </head>
    <body>
        {{ $slot }}
    </body>
</html>

Sử dụng:

blade
<x-layout>
    <x-slot:title>
        Trang chủ
    </x-slot>

    <h1>Xin chào!</h1>
</x-layout>

Layouts dùng Template Inheritance

blade
<!-- resources/views/layouts/app.blade.php -->
<html>
    <head>
        <title>Ứng dụng - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            Sidebar chính.
        @show

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

Kế thừa layout:

blade
@extends('layouts.app')

@section('title', 'Trang chủ')

@section('sidebar')
    @parent
    <p>Thêm vào sidebar.</p>
@endsection

@section('content')
    <p>Nội dung chính.</p>
@endsection

Forms

CSRF Field

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

Method Field

blade
<form action="/example" method="POST">
    @method('PUT')
    @csrf
    ...
</form>

Validation Errors

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

<label for="title">Tiêu đề bài viết</label>
<input id="title" type="text" class="@error('title') is-invalid @enderror">

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

Stacks

Push vào named stacks để render ở nơi khác:

blade
@push('scripts')
    <script src="/example.js"></script>
@endpush

Render stack:

blade
<head>
    @stack('scripts')
</head>

Service Injection

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

<div>
    Doanh thu hàng tháng: {{ $metrics->monthlyRevenue() }}.
</div>

Mở rộng Blade (Extending Blade)

Directives tùy chỉnh

Đăng ký trong method boot của AppServiceProvider:

php
use Illuminate\Support\Facades\Blade;

Blade::directive('datetime', function (string $expression) {
    return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
});

Sử dụng:

blade
@datetime($var)

Custom If Statements

php
Blade::if('disk', function (string $value) {
    return config('filesystems.default') === $value;
});
blade
@disk('local')
    // Ứng dụng đang dùng local disk...
@elsedisk('s3')
    // Ứng dụng đang dùng s3 disk...
@enddisk