Giao diện
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>
@endverbatimBlade 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!
@endifBlade 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"...
@endemptyAuthentication Directives
blade
@auth
// User đã authenticated...
@endauth
@guest
// User chưa authenticated...
@endguestSwitch Statements
blade
@switch($i)
@case(1)
Giá trị đầu...
@break
@case(2)
Giá trị thứ hai...
@break
@default
Giá trị mặc định...
@endswitchLoops
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>
@endwhileBiến $loop
Bên trong loops, biến $loop cung cấp thông tin hữu ích:
| Property | Mô tả |
|---|---|
$loop->index | Index hiện tại (bắt đầu từ 0) |
$loop->iteration | Iteration hiện tại (bắt đầu từ 1) |
$loop->remaining | Iterations còn lại |
$loop->count | Tổng số items |
$loop->first | Có phải iteration đầu tiên |
$loop->last | Có phải iteration cuối cùng |
$loop->even | Có phải iteration chẵn |
$loop->odd | Có phải iteration lẻ |
$loop->depth | Mức lồng nhau |
$loop->parent | Biế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;
@endphpComments
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 AlertTạ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>
@endsectionForms
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>
@enderrorStacks
Push vào named stacks để render ở nơi khác:
blade
@push('scripts')
<script src="/example.js"></script>
@endpushRender 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