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