Life Cycle Laravel

Life Cycle Laravel

27.09.2024
Author: ADMIN

Laravel, một framework PHP phổ biến, có một vòng đời (life cycle) riêng cho mỗi request. Hãy cùng xem qua các giai đoạn chính trong vòng đời của một request trong Laravel:

  1. Entry Point (Điểm vào)

Tất cả các requests đều đi qua file public/index.php:

<?php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

define('LARAVEL_START', microtime(true));

require __DIR__.'/../vendor/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = $kernel->handle(
    $request = Request::capture()
)->send();

$kernel->terminate($request, $response);
  1. Autoloading

Composer’s autoloader được load.

  1. Create Application Instance

Một instance của ứng dụng Laravel được tạo ra.

  1. Kernel

HTTP Kernel hoặc Console Kernel được tạo ra, tùy thuộc vào loại request.

  1. Service Providers
public function register()
{
    //
}

public function boot()
{
    //
}

Service Providers được đăng ký (register) và khởi động (boot).

  1. Middleware

Request đi qua global middleware:

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
  1. Routing

Router xác định route phù hợp và chạy route middleware:

Route::get('/user', 'UserController@index')->middleware('auth');
  1. Controller

Controller xử lý request và trả về response:

public function index()
{
    return view('users.index', ['users' => User::all()]);
}
  1. Response

Response được gửi trở lại cho client.

  1. Termination

Sau khi response được gửi, các termination tasks được thực hiện:

$kernel->terminate($request, $response);

Hiểu rõ về vòng đời này sẽ giúp bạn can thiệp vào đúng thời điểm trong quá trình xử lý request, ví dụ như đăng ký service providers, thêm middleware, hoặc xử lý logic trong controllers.

How to use Laravel Reverb

How to use Laravel Reverb

07.09.2024
Author: ADMIN

Laravel Reverb là một máy chủ WebSocket chính thức cho các ứng dụng Laravel, cung cấp khả năng giao tiếp theo thời gian thực giữa máy khách và máy chủ một cách liền mạch.

Laravel Reverb có nhiều tính năng hấp dẫn, bao gồm:

  • Tốc độ và khả năng mở rộng.
  • Hỗ trợ hàng nghìn kết nối đồng thời.
  • Tích hợp với các tính năng phát sóng hiện có của Laravel.
  • Tương thích với Laravel Echo.
  • Tích hợp và triển khai hàng đầu với Laravel Forge.

Trong hướng dẫn này, tôi sẽ hướng dẫn bạn cách sử dụng Laravel Reverb để phát triển một ứng dụng Laravel thời gian thực. Bạn sẽ học về các kênh, sự kiện, phát sóng, và cách sử dụng Laravel Reverb để tạo ra các ứng dụng nhanh chóng và thời gian thực trong Laravel.

Hơn nữa, bạn sẽ học cách thêm thông báo thời gian thực vào ứng dụng Laravel Reverb của mình!

  1. Cài đặt một ứng dụng Laravel mới
    composer create-project laravel/laravel laravel-reverb-chat

    Chuyển đến thư mục dự án của bạn:

    cd laravel-reverb-chat
  2. Installing Laravel Reverb
    Cài đặt Laravel Reverb bằng cách chạy câu lệnh sau:
    php artisan install:broadcasting
    npm install --save laravel-echo pusher-js

    Chú ý: các lựa chọn default

    Sau khi bạn đã cài đặt Reverb, bạn có thể chỉnh sửa cấu hình của nó từ tệp `config / reverb.php`. Để thiết lập kết nối đến Reverb, một bộ thông tin đăng nhập ứng dụng Reverb phải được trao đổi giữa máy khách và máy chủ. Những thông tin đăng nhập này được cấu hình trên máy chủ và được sử dụng để xác minh yêu cầu từ máy khách. Bạn có thể xác định những thông tin đăng nhập này bằng cách sử dụng các biến môi trường sau:

    BROADCAST_DRIVER=reverb
    REVERB_APP_ID=my-app-id
    REVERB_APP_KEY=my-app-key
    REVERB_APP_SECRET=my-app-secret
  3. Running Server
    Bạn có thể khởi chạy máy chủ Reverb bằng cách sử dụng command reverb:start:
    php artisan reverb:start

    Mặc định, máy chủ Reverb sẽ được khởi động tại 0.0.0.0:8080, điều này làm cho nó có thể truy cập từ tất cả các giao diện mạng. Nếu bạn muốn thiết lập một máy chủ hoặc cổng cụ thể, bạn có thể sử dụng các tùy chọn --host--port khi khởi động máy chủ.

    php artisan reverb:start --host=127.0.0.1 --port=9000

    Bạn cũng có thể xác định các biến môi trường REVERB_SERVER_HOST REVERB_SERVER_PORT trong tệp cấu hình .env của ứng dụng của bạn.

  4. Setup Database
    Mở tệp .env của bạn và điều chỉnh cài đặt để thiết lập cơ sở dữ liệu của bạn. Dưới đây là một ví dụ sử dụng MySQL để đơn giản hóa:
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=laravel
    DB_USERNAME=root
    DB_PASSWORD=

    Đối với bản demo này, chúng ta sẽ tạo năm phòng được xác định trước. Hãy bắt đầu bằng cách tạo một migration cho một bảng rooms.

    php artisan make:model Room --migration

    Để đơn giản hóa, chỉ cần tạo trường name cho model này và chạy migration.

    Schema::create('rooms', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
    php artisan migrate

    Sau đó, seed dữ liệu cho database với 5 room. Tạo một seeder:

    php artisan make:seeder RoomsTableSeeder 
    <?php
    
    namespace Database\Seeders;
    
    use Illuminate\Database\Seeder;
    use Illuminate\Support\Facades\DB;
    
    class RoomsTableSeeder extends Seeder
    {
        /**
         * Run the database seeds.
         */
        public function run(): void
        {
            DB::table('rooms')->insert([
                ['name' => 'Room 1'],
                ['name' => 'Room 2'],
                ['name' => 'Room 3'],
                ['name' => 'Room 4'],
                ['name' => 'Room 5'],
            ]);
        }
    }
    
    Run seeder:
    php artisan db:seed --class=RoomsTableSeeder
  5. Tạo Event
    Trong thư mục app/Events, tạo một file mới tên là MessageSent.php. File này chịu trách nhiệm phát sóng các tin nhắn mới tới các phòng chat cụ thể. Dưới đây là mẫu cơ bản:
    php artisan make:event MessageSent

    class MessageSent implements ShouldBroadcast
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
    
        public $userName;
        public $roomId;
        public $message;
    
        public function __construct($userName, $roomId, $message)
        {
            $this->userName = $userName;
            $this->roomId = $roomId;
            $this->message = $message;
        }
    
        public function broadcastOn() : Channel
        {
    
            return new Channel('chat.' . $this->roomId);
        }
    
        public function broadcastWith()
        {
            return [
                'userName' => $this->userName,
                'message' => $this->message,
            ];
        }
    }
  6. Tạo Pages
    Trong dự án này, chúng ta sẽ có hai trang: một trang để hiển thị danh sách các phòng và một trang cho từng phòng chat riêng biệt. Chúng ta sẽ bắt đầu bằng cách tạo các template Blade để hiển thị các phòng. Đặt tên các view này là index.blade.phpchat.blade.php và lưu chúng trong thư mục rooms dưới resources/views. Tiếp theo, chúng ta sẽ tạo một controller và một route để điều hướng tới các trang này.
    php artisan make:view rooms/index
    php artisan make:view rooms/chat

    index.blade.php
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Chat Rooms</title>
    </head>
    
    <body>
        <div id="app">
            <h1>Chat Rooms</h1>
            <ul>
                @foreach ($rooms as $room)
                    <li>
                        <a href="{{ route('rooms.show', $room->id) }}">Join {{ $room->name }}</a>
                    </li>
                @endforeach
            </ul>
        </div>
    </body>
    
    </html>
    

    chat.blade.php

    Thiết lập một form cơ bản để hiển thị các tin nhắn và một trường nhập liệu đơn giản để gửi tin nhắn. Đảm bảo rằng bạn đã import Echo và Pusher vào file app.js.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Chat Room: {{ $room->name }}</title>
        @vite(['resources/css/app.css'])
        @vite(['resources/js/app.js'])
    </head>
    
    <body>
        <div id="app">
            <h2>Chat Room: {{ $room->name }}</h2>
            <div id="messages"
                style="border: 1px solid #ccc; margin-bottom: 10px; padding: 10px; height: 300px; overflow-y: scroll;">
                <!-- Messages will be displayed here -->
            </div>
            <input type="text" id="messageInput" placeholder="Type your message here..." autofocus>
            <button onclick="sendMessage()">Send</button>
        </div>
    
        <script>
            document.addEventListener('DOMContentLoaded', function() {
                const roomId = "{{ $room->id }}";
                Echo.channel(`chat.${roomId}`)
                    .listen('MessageSent', (e) => {
                        const messages = document.getElementById('messages');
                        const messageElement = document.createElement('div');
                        messageElement.innerHTML = `<strong>${e.userName}:</strong> ${e.message}`;
                        messages.appendChild(messageElement);
                        messages.scrollTop = messages.scrollHeight; // Scroll to the bottom
                    });
            })
    
            function sendMessage() {
                const messageInput = document.getElementById('messageInput');
                const message = messageInput.value;
                messageInput.value = ''; // Clear input
                const roomId = "{{ $room->id }}"
                fetch(`/rooms/${roomId}/message`, {
                    method: 'POST',
                    headers: {
                        'X-CSRF-TOKEN': '{{ csrf_token() }}',
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        message: message
                    })
                }).catch(error => console.error('Error:', error));
            }
        </script>
    </body>
    
    </html>
    

    app.js

    import Echo from 'laravel-echo';
    
    import Pusher from 'pusher-js';
    window.Pusher = Pusher;
    
    window.Echo = new Echo({
        broadcaster: 'reverb',
        key: import.meta.env.VITE_REVERB_APP_KEY,
        wsHost: import.meta.env.VITE_REVERB_HOST,
        wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
        wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
        forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
        enabledTransports: ['ws', 'wss'],
    });

    Tiếp theo hãy tạo Controller

    php artisan make:controller RoomsController
    <?php
    
    namespace App\Http\Controllers;
    
    use App\Models\Room;
    
    class RoomsController extends Controller
    {
        public function index()
        {
            $rooms = Room::all();
            return view('rooms.index', [
                'rooms' => $rooms
            ]);
        }
    
        public function show(Room $room)
        {
            return view('rooms.chat', [
                'roomId' => $room->id,
                'room' => $room,
                'messages' => []
            ]);
        }
    }
    

    Để đơn giản, hãy tạo một endpoint postMessage và thêm nó vào web.php.

    php artisan make:controller ChatController
    <?php
    
    namespace App\Http\Controllers;
    
    use App\Events\MessageSent;
    use Illuminate\Http\Request;
    use Illuminate\Support\Str;
    
    class ChatController extends Controller
    {
        public function postMessage(Request $request, $roomId)
        {
            $userName = 'User_' . Str::random(4);
            $messageContent = $request->input('message');
            MessageSent::dispatch($userName, $roomId, $messageContent);
            return response()->json(['status' => 'Message sent successfully.']);
        }
    }
    
    routes/web.php
    Route::get('/rooms', [RoomsController::class, 'index'])->name('rooms.index');
    Route::get('/rooms/{room}', [RoomsController::class, 'show'])->name('rooms.show');
    Route::post('/rooms/{roomId}/message', [ChatController::class, 'postMessage'])->name('api.rooms.message.post');
  7. Run Project
    Để chạy dự án Laravel, chúng ta cần thực thi các lệnh sau:
    - Khởi động Laravel:
    php artisan serve
    

    - Khởi động frontend:

    npm run dev
    

    - Bắt đầu queue:

    php artisan queue:listen
    

    - Run Reverb:

    php artisan reverb:start
    

Để biết thông tin chi tiết hơn, bạn có thể kiểm tra tài liệu hướng dẫn chính thức của Laravel Reverb. Chúc các bạn thành công

Soft Deletes

Soft Deletes

06.09.2024
Author: ADMIN

Trong bài viết này, chúng ta sẽ tìm hiểu về một tính năng rất hữu ích trong Laravel - Soft Deletes

Trong Laravel, "Soft Deletes" là một tính năng giúp bạn có thể xóa bản ghi mà không thực sự xóa nó khỏi cơ sở dữ liệu. Thay vào đó, bản ghi sẽ được đánh dấu là đã bị xóa bằng cách thiết lập một trường deleted_at với thời gian xóa. Bản ghi vẫn tồn tại trong cơ sở dữ liệu nhưng sẽ không được hiển thị trong các truy vấn mặc định.

Cách sử dụng Soft Deletes trong Laravel

  1. Thêm Soft Deletes vào Model: Đầu tiên, bạn cần thêm SoftDeletes trait vào model của mình.

    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    
    class Post extends Model
    {
        use SoftDeletes;
    
        // Các thuộc tính khác của model
    
        protected $dates = ['deleted_at'];
    }
    
  2. Thêm cột deleted_at vào bảng: Bạn cần phải thêm một cột deleted_at vào bảng tương ứng với model của bạn để lưu trữ thời gian xóa. Bạn có thể làm điều này bằng cách tạo một migration:
    php artisan make:migration add_deleted_at_to_posts_table --table=posts
    

    Trong file migration:

    Schema::table('posts', function (Blueprint $table) {
        $table->softDeletes(); // Thêm cột deleted_at
    });
    

    Sau đó, chạy lệnh migrate:

    php artisan migrate
    
  3. Sử dụng Soft Deletes trong truy vấn:

    • Để xóa mềm một bản ghi, sử dụng phương thức delete():

      $post = Post::find(1);
      $post->delete();
      
    • Để khôi phục một bản ghi đã xóa mềm, sử dụng phương thức restore():
      $post = Post::withTrashed()->find(1);
      $post->restore();
      
    • Để xóa cứng (xóa vĩnh viễn) một bản ghi đã xóa mềm, sử dụng phương thức forceDelete():
      $post->forceDelete();
      
    • Để lấy tất cả các bản ghi, bao gồm cả những bản ghi đã bị xóa mềm, sử dụng phương thức withTrashed():
      $posts = Post::withTrashed()->get();
      
    • Để chỉ lấy các bản ghi đã bị xóa mềm, sử dụng phương thức onlyTrashed():
      $trashedPosts = Post::onlyTrashed()->get();
      

Lợi ích của Soft Deletes

  • Khôi phục dữ liệu: Cho phép bạn khôi phục lại các bản ghi đã bị xóa.
  • An toàn: Tránh xóa nhầm dữ liệu, đặc biệt là khi cần duyệt lại hoặc kiểm toán dữ liệu đã bị xóa.
Eloquent Collections

Eloquent Collections

04.09.2024
Author: ADMIN

Eloquent Collections trong Laravel là một tính năng mạnh mẽ cho phép bạn làm việc với tập hợp các model được truy vấn từ cơ sở dữ liệu. Mỗi khi bạn thực hiện một truy vấn Eloquent, kết quả trả về thường là một đối tượng của Illuminate\Database\Eloquent\Collection. Các Eloquent Collection mở rộng từ Laravel Collection, cung cấp các phương thức hữu ích để thao tác và xử lý dữ liệu một cách dễ dàng.

1. Tổng quan về Eloquent Collections

Khi bạn truy xuất nhiều bản ghi từ cơ sở dữ liệu bằng Eloquent, Laravel sẽ trả về một Collection chứa các model. Ví dụ:

$users = User::all();

Biến $users ở đây sẽ là một instance của Illuminate\Database\Eloquent\Collection, chứa tất cả các đối tượng User trong cơ sở dữ liệu.

Eloquent Collections cung cấp các phương thức mạnh mẽ cho phép bạn duyệt qua, lọc, sắp xếp, và biến đổi các tập hợp model mà không cần phải viết mã phức tạp.

2. Phương thức phổ biến trong Eloquent Collections

  • append

    Phương thức append cho phép bạn thêm các thuộc tính ảo vào một collection. Các thuộc tính này không có trong cơ sở dữ liệu nhưng được định nghĩa trong model thông qua Accessors.

    Ví dụ:
    $users = User::all()->append('full_name');
    

    Ở đây, full_name là một accessor được định nghĩa trong model User. Thuộc tính này sẽ được thêm vào mỗi model trong collection.

  • contains

    Phương thức contains kiểm tra xem collection có chứa một phần tử cụ thể không. Bạn có thể kiểm tra bằng cách so sánh giá trị thuộc tính hoặc kiểm tra đối tượng model.

    Ví dụ:
    $containsUser = $users->contains('id', 1);
    $containsUser = $users->contains($someUser);
    

    Phương thức này trả về true nếu collection chứa phần tử, ngược lại trả về false.

  • diff

    Phương thức diff so sánh hai collection và trả về phần tử có trong collection hiện tại nhưng không có trong collection so sánh.

    Ví dụ:
    $users1 = User::where('status', 'active')->get();
    $users2 = User::where('status', 'inactive')->get();
    $diff = $users1->diff($users2);
    

    Kết quả là các phần tử có trong $users1 nhưng không có trong $users2.

  • except

    Phương thức except tạo một collection mới bằng cách loại bỏ các phần tử có khóa hoặc chỉ số cụ thể.

    Ví dụ:
    $users = User::all();
    $usersExceptFirst = $users->except([0]);
    

    Kết quả là một collection mới không chứa phần tử tại chỉ số 0.

  • find

    Phương thức find tìm kiếm phần tử trong collection dựa trên giá trị của khóa chính.

    Ví dụ:
    $user = $users->find(1);
    

    Phương thức này trả về model có ID là 1, hoặc null nếu không tìm thấy.

  • 6. fresh

    Phương thức fresh tải lại model từ cơ sở dữ liệu, cập nhật các thuộc tính của model với giá trị mới nhất.

    Ví dụ:
    $user = User::find(1);
    $user->name = 'New Name';
    $user->fresh();
    

    Sau khi gọi fresh(), các thuộc tính của model sẽ được làm mới từ cơ sở dữ liệu.

  • intersect

    Phương thức intersect trả về phần giao nhau của hai collection.

    Ví dụ:
    $users1 = User::where('status', 'active')->get();
    $users2 = User::where('status', 'inactive')->get();
    $intersect = $users1->intersect($users2);
    

    Kết quả là các phần tử có trong cả $users1$users2.

  • load

    Phương thức load eager load các quan hệ cho collection của các model.

    Ví dụ:
    $users = User::all()->load('posts');
    

    Phương thức này sẽ tải trước quan hệ posts cho tất cả người dùng trong collection.

  • loadMissing

    Phương thức loadMissing tương tự như load, nhưng chỉ tải các quan hệ còn thiếu, không tải lại các quan hệ đã được tải trước đó.

    Ví dụ:
    $users = User::with('posts')->get();
    $users->loadMissing('comments');
    

    comments chỉ được tải nếu chưa được tải từ trước đó.

  • modelKeys

    Phương thức modelKeys trả về một collection chứa các khóa chính của các model trong collection.

    Ví dụ:
    $keys = $users->modelKeys();
    

    Kết quả là một mảng các ID của các người dùng trong collection.

  • makeVisible

    Phương thức makeVisible thêm các thuộc tính ẩn vào collection, làm cho chúng có thể truy cập được.

    Ví dụ:
    $users = User::all()->makeVisible(['secret_field']);
    

    secret_field sẽ được thêm vào thuộc tính của model trong collection.

  • makeHidden

    Phương thức makeHidden ẩn các thuộc tính khỏi collection.

    Ví dụ:
    $users = User::all()->makeHidden(['secret_field']);
    

    secret_field sẽ bị ẩn và không còn có thể truy cập được.

  • only

    Phương thức only tạo một collection mới chỉ với các phần tử có khóa cụ thể.

    Ví dụ:
    $users = User::all()->only(['id', 'name']);
    

    Kết quả là một collection mới chỉ chứa các trường idname.

  • setVisible

    Phương thức setVisible thiết lập các thuộc tính của model mà bạn muốn hiển thị trong collection.

    Ví dụ:
    $users = User::all()->setVisible(['name', 'email']);
    

    Chỉ các thuộc tính nameemail sẽ được hiển thị trong collection.

  • setHidden

    Phương thức setHidden thiết lập các thuộc tính của model mà bạn muốn ẩn trong collection.

    Ví dụ:
    $users = User::all()->setHidden(['password']);
    

    Thuộc tính password sẽ bị ẩn và không được hiển thị.

  • toQuery

    Phương thức toQuery trả về một query builder cho collection.

    Ví dụ:
    $query = User::all()->toQuery();
    

    $query là một instance của Illuminate\Database\Eloquent\Builder và có thể tiếp tục được sử dụng để thực hiện các truy vấn.

  • unique

    Phương thức unique loại bỏ các phần tử trùng lặp trong collection dựa trên một thuộc tính hoặc một hàm callback.

    Ví dụ:
    $uniqueUsers = $users->unique('email');
    

    Kết quả là một collection mới chỉ chứa các người dùng có email duy nhất.

Ngoài ra, bạn có thể tham khảo thêm các method khác tại đây

Eloquent Accessors and Mutators

Eloquent Accessors and Mutators

30.08.2024
Author: ADMIN

Eloquent Accessors và Mutators là các phương thức trong Eloquent của Laravel cho phép bạn điều chỉnh cách dữ liệu được lấy ra hoặc lưu vào cơ sở dữ liệu. Đây là một tính năng mạnh mẽ giúp bạn dễ dàng thao tác và định dạng dữ liệu mà không cần thay đổi logic truy vấn.

1. Accessors (Bộ lấy dữ liệu)

Accessors cho phép bạn thay đổi giá trị của một thuộc tính trước khi trả về nó cho ứng dụng. Điều này giúp bạn có thể định dạng dữ liệu theo cách mong muốn mỗi khi truy vấn model.

Cách sử dụng:

Bạn định nghĩa một accessor bằng cách tạo một phương thức trong model với tên theo cú pháp get{Attribute}Attribute, trong đó {Attribute} là tên của thuộc tính bạn muốn định dạng.

Ví dụ:

Giả sử bạn có một model User với thuộc tính first_namelast_name. Bạn muốn kết hợp chúng thành một thuộc tính full_name khi lấy dữ liệu từ model:

class User extends Model
{
    public function getFullNameAttribute()
    {
        return "{$this->first_name} {$this->last_name}";
    }
}

Bây giờ, bạn có thể truy cập thuộc tính full_name như thể nó là một cột trong bảng:

$user = User::find(1);
echo $user->full_name; // John Doe

Laravel sẽ tự động gọi phương thức getFullNameAttribute() mỗi khi bạn truy cập vào thuộc tính full_name.

2. Mutators (Bộ chỉnh sửa dữ liệu)

Mutators cho phép bạn thay đổi giá trị của một thuộc tính trước khi lưu nó vào cơ sở dữ liệu. Điều này rất hữu ích khi bạn muốn đảm bảo dữ liệu luôn được lưu theo định dạng nhất định.

Cách sử dụng:

Bạn định nghĩa một mutator bằng cách tạo một phương thức trong model với tên theo cú pháp set{Attribute}Attribute, trong đó {Attribute} là tên của thuộc tính bạn muốn thay đổi.

Ví dụ:

Giả sử bạn muốn đảm bảo rằng tất cả các tên người dùng (username) được lưu vào cơ sở dữ liệu đều ở dạng chữ thường:

class User extends Model
{
    public function setUsernameAttribute($value)
    {
        $this->attributes['username'] = strtolower($value);
    }
}

Khi bạn gán giá trị cho thuộc tính username, Laravel sẽ tự động gọi phương thức setUsernameAttribute():

$user = new User;
$user->username = 'JohnDoe';
$user->save();

// username được lưu dưới dạng 'johndoe'

3. Tùy chỉnh thuộc tính với Accessors và Mutators

Bạn có thể sử dụng cả Accessors và Mutators để tạo ra các thuộc tính tuỳ chỉnh không tồn tại trong cơ sở dữ liệu. Đây là cách bạn có thể thao tác với dữ liệu mà không ảnh hưởng đến các cột thực tế trong bảng.

Ví dụ:

Giả sử bạn có một cột birthdate lưu trữ ngày sinh của người dùng. Bạn muốn tạo một thuộc tính age để tính toán tuổi từ ngày sinh:

class User extends Model
{
    public function getAgeAttribute()
    {
        return \Carbon\Carbon::parse($this->birthdate)->age;
    }
}

Bây giờ, bạn có thể truy cập thuộc tính age một cách dễ dàng:

$user = User::find(1);
echo $user->age; // 30

4. Lợi ích của Accessors và Mutators

  1. Tăng tính dễ đọc của mã nguồn: Accessors và Mutators giúp mã của bạn trở nên dễ đọc hơn bằng cách đóng gói logic xử lý dữ liệu vào trong model.
  2. Đảm bảo tính nhất quán của dữ liệu: Bằng cách sử dụng Mutators, bạn có thể đảm bảo rằng dữ liệu luôn được lưu vào cơ sở dữ liệu theo một định dạng chuẩn xác.
  3. Tính linh hoạt: Accessors cho phép bạn định dạng dữ liệu theo nhu cầu mà không cần phải thay đổi cấu trúc cơ sở dữ liệu.

5. Các trường hợp sử dụng phổ biến

  • Accessors thường được sử dụng để định dạng dữ liệu khi truy xuất, ví dụ như định dạng ngày tháng, kết hợp nhiều cột thành một, hoặc chuyển đổi mã sang định dạng hiển thị.

  • Mutators thường được sử dụng để xử lý dữ liệu trước khi lưu vào cơ sở dữ liệu, ví dụ như chuyển văn bản sang chữ thường, mã hóa mật khẩu, hoặc định dạng số điện thoại.

Kết luận

Eloquent Accessors và Mutators là công cụ mạnh mẽ trong Laravel giúp bạn quản lý và thao tác dữ liệu một cách dễ dàng và linh hoạt. Bằng cách sử dụng các phương thức này, bạn có thể đảm bảo rằng dữ liệu được định dạng và lưu trữ một cách nhất quán, đồng thời giữ cho mã nguồn của bạn trở nên dễ đọc và dễ bảo trì hơn.

Polymorphic Relationships

Polymorphic Relationships

30.08.2024
Author: ADMIN

Polymorphic Relationships là một tính năng mạnh mẽ trong Eloquent của Laravel cho phép một model có thể liên kết với nhiều model khác nhau bằng cách sử dụng một bảng quan hệ duy nhất. Đây là mối quan hệ đặc biệt thường được sử dụng khi một thực thể có thể thuộc về nhiều loại thực thể khác nhau.

1. One-to-One Polymorphic Relationships

One-to-One Polymorphic Relationships cho phép một model có thể liên kết với một model khác trong mối quan hệ một-một, nhưng với khả năng liên kết với nhiều loại model khác nhau. Ví dụ, bạn có thể có một bảng image chứa các hình ảnh cho cả người dùng (users) và bài viết (posts). Một hình ảnh có thể thuộc về một bài viết hoặc một người dùng.

Ví dụ:

  1. Cấu trúc cơ sở dữ liệu:

    Đầu tiên, bạn cần tạo các bảng users, posts, và images. Bảng images sẽ chứa hai cột đặc biệt là imageable_idimageable_type để xác định model mà hình ảnh thuộc về.

    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
    
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->timestamps();
    });
    
    Schema::create('images', function (Blueprint $table) {
        $table->id();
        $table->string('url');
        $table->morphs('imageable');
        $table->timestamps();
    });
    

    Ở đây, morphs('imageable') sẽ tạo hai cột imageable_idimageable_type.

  2. Định nghĩa quan hệ trong model:

    • Trong model Image, bạn sẽ định nghĩa phương thức imageable để chỉ ra rằng hình ảnh này có thể thuộc về nhiều loại model khác nhau:
      class Image extends Model
      {
          public function imageable()
          {
              return $this->morphTo();
          }
      }
      
    • Trong model UserPost, bạn sẽ định nghĩa một phương thức image để chỉ ra rằng người dùng và bài viết có thể có một hình ảnh:
      class User extends Model
      {
          public function image()
          {
              return $this->morphOne(Image::class, 'imageable');
          }
      }
      
      class Post extends Model
      {
          public function image()
          {
              return $this->morphOne(Image::class, 'imageable');
          }
      }
      
  3. Sử dụng One-to-One Polymorphic Relationship:

    Bạn có thể thêm và lấy hình ảnh cho người dùng và bài viết như sau:

    $user = User::find(1);
    $image = new Image(['url' => 'user_image.jpg']);
    $user->image()->save($image);
    
    $post = Post::find(1);
    $image = new Image(['url' => 'post_image.jpg']);
    $post->image()->save($image);
    

    Để lấy hình ảnh của một người dùng hoặc bài viết:

    $userImage = $user->image;
    $postImage = $post->image;
    

2. One-to-Many Polymorphic Relationships

One-to-Many Polymorphic Relationships cho phép một model có thể liên kết với nhiều model khác nhau. Ví dụ điển hình là một bảng comments có thể chứa các bình luận cho cả bài viết (posts) và video (videos). Cả hai model PostVideo có thể chia sẻ cùng một bảng comments.

Ví dụ:
  1. Cấu trúc cơ sở dữ liệu:

    Bạn cần có các bảng posts, videos, và comments. Bảng comments sẽ chứa hai cột đặc biệt là commentable_idcommentable_type để theo dõi ID và loại model mà nó liên kết.

    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->timestamps();
    });
    
    Schema::create('videos', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->timestamps();
    });
    
    Schema::create('comments', function (Blueprint $table) {
        $table->id();
        $table->text('body');
        $table->morphs('commentable');
        $table->timestamps();
    });
    

    Ở đây, morphs('commentable') là một shortcut để tạo hai cột commentable_idcommentable_type.

  2. Định nghĩa quan hệ trong model:

    • Trong model Comment, bạn sẽ định nghĩa một phương thức commentable để chỉ ra rằng comment này có thể thuộc về nhiều model khác nhau:
      class Comment extends Model
      {
          public function commentable()
          {
              return $this->morphTo();
          }
      }
      
    • Trong model PostVideo, bạn sẽ định nghĩa một phương thức comments để chỉ ra rằng các bài viết và video có thể có nhiều comment:
      class Post extends Model
      {
          public function comments()
          {
              return $this->morphMany(Comment::class, 'commentable');
          }
      }
      
      class Video extends Model
      {
          public function comments()
          {
              return $this->morphMany(Comment::class, 'commentable');
          }
      }
      
  3. Sử dụng Polymorphic Relationship:

    Bạn có thể thêm và lấy các bình luận cho các bài viết và video như sau:

    $post = Post::find(1);
    $comment = new Comment(['body' => 'Great post!']);
    $post->comments()->save($comment);
    
    $video = Video::find(1);
    $comment = new Comment(['body' => 'Nice video!']);
    $video->comments()->save($comment);
    

    Để lấy tất cả các bình luận cho một bài viết hoặc video:

    $postComments = $post->comments;
    $videoComments = $video->comments;
    

3. Many-to-Many Polymorphic Relationships

Many-to-Many Polymorphic Relationships cho phép một model có thể có mối quan hệ nhiều-nhiều với nhiều model khác nhau. Ví dụ, một bảng tags có thể được liên kết với cả postsvideos.

Ví dụ:
  1. Cấu trúc cơ sở dữ liệu:

    Bạn cần có các bảng posts, videos, tags, và taggables. Bảng taggables sẽ chứa hai cột taggable_idtaggable_type để xác định loại thực thể mà nó liên kết (bài viết hoặc video).

    Schema::create('tags', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });
    
    Schema::create('taggables', function (Blueprint $table) {
        $table->morphs('taggable');
        $table->foreignId('tag_id')->constrained();
        $table->timestamps();
    });
    
  2. Định nghĩa quan hệ trong model:

    • Trong model Tag, bạn sẽ định nghĩa phương thức taggables để chỉ ra rằng tag này có thể thuộc về nhiều loại model khác nhau:
      class Tag extends Model
      {
          public function taggables()
          {
              return $this->morphedByMany(Post::class, 'taggable');
          }
      }
      
    • Trong model PostVideo, bạn sẽ định nghĩa một phương thức tags để chỉ ra rằng bài viết và video có thể có nhiều tag:
      class Post extends Model
      {
          public function tags()
          {
              return $this->morphToMany(Tag::class, 'taggable');
          }
      }
      
      class Video extends Model
      {
          public function tags()
          {
              return $this->morphToMany(Tag::class, 'taggable');
          }
      }
      
  3. Sử dụng Many-to-Many Polymorphic Relationship:

    Bạn có thể thêm và lấy các tag cho bài viết và video như sau:

    $post = Post::find(1);
    $tag = Tag::find(1);
    $post->tags()->attach($tag);
    
    $video = Video::find(1);
    $video->tags()->attach($tag);
    

    Để lấy tất cả các tag cho một bài viết hoặc video:

    $postTags = $post->tags;
    $videoTags = $video->tags;
    

4. Lợi ích của Polymorphic Relationships

  1. Tính linh hoạt: Bạn có thể thiết kế cơ sở dữ liệu linh hoạt hơn, cho phép các thực thể khác nhau có thể chia sẻ cùng một bảng quan hệ.
  2. Tái sử dụng: Polymorphic Relationships giúp tránh lặp lại các bảng quan hệ không cần thiết, giảm phức tạp của cơ sở dữ liệu.
  3. Tiết kiệm thời gian: Bạn có thể quản lý nhiều loại dữ liệu mà không cần phải tạo ra quá nhiều bảng phụ thuộc, giúp tiết kiệm thời gian trong quá trình phát triển và bảo trì.

Kết luận

Polymorphic Relationships trong Laravel là một công cụ cực kỳ mạnh mẽ và linh hoạt giúp bạn quản lý các mối quan hệ phức tạp trong cơ sở dữ liệu. Việc hiểu rõ và tận dụng tính năng này sẽ giúp bạn tối ưu hóa cấu trúc dữ liệu và mã nguồn của mình, đồng thời làm cho quá trình phát triển ứng dụng trở nên dễ dàng hơn.

Eloquent Query Scopes

Eloquent Query Scopes

30.08.2024
Author: ADMIN

Eloquent Query Scopes là một tính năng mạnh mẽ trong Laravel, giúp bạn tái sử dụng các đoạn mã truy vấn một cách dễ dàng. Bằng cách định nghĩa các scope, bạn có thể gom nhóm các truy vấn phức tạp thành các phương thức có thể tái sử dụng trên nhiều nơi trong ứng dụng.

Tổng quan

1. Local Scopes (Phạm vi cục bộ)

Local scopes cho phép bạn định nghĩa một truy vấn cụ thể ngay trong model và có thể được gọi trực tiếp từ các truy vấn Eloquent. Một scope cục bộ được định nghĩa bằng cách tạo một phương thức trong model và bắt đầu tên phương thức bằng từ khoá scope.

Ví dụ:

Giả sử bạn có một model User và bạn muốn tạo một scope để lấy tất cả các người dùng đã kích hoạt:

class User extends Model
{
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

Bạn có thể sử dụng scope này trong các truy vấn của mình như sau:

$activeUsers = User::active()->get();

Phương thức scopeActive sẽ được gọi một cách tự động khi bạn sử dụng active() trong truy vấn. Scope này giúp mã trở nên ngắn gọn, dễ đọc và có thể tái sử dụng nhiều lần.

2. Dynamic Scopes (Phạm vi động)

Dynamic scopes cho phép bạn truyền tham số vào các phương thức scope để tuỳ chỉnh truy vấn dựa trên tham số đó.

Ví dụ:

Nếu bạn muốn tạo một scope để lấy người dùng dựa trên độ tuổi:

class User extends Model
{
    public function scopeOfAge($query, $age)
    {
        return $query->where('age', $age);
    }
}

Bạn có thể sử dụng scope này như sau:

$users = User::ofAge(25)->get();

Scope ofAge sẽ nhận một tham số $age và trả về danh sách người dùng có độ tuổi tương ứng.

3. Global Scopes (Phạm vi toàn cục)

Global scopes được áp dụng tự động trên mọi truy vấn của một model. Chúng thường được sử dụng khi bạn muốn áp dụng một điều kiện chung cho tất cả các truy vấn liên quan đến model đó. Để tạo một global scope, bạn cần định nghĩa một class riêng biệt và implement interface Scope.

Ví dụ:

Giả sử bạn muốn áp dụng một scope để chỉ lấy những người dùng đã kích hoạt trong tất cả các truy vấn liên quan đến model User:

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class ActiveScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        return $builder->where('active', 1);
    }
}

Sau đó, bạn thêm scope này vào trong model User:

class User extends Model
{
    protected static function booted()
    {
        static::addGlobalScope(new ActiveScope);
    }
}

Bây giờ, mọi truy vấn liên quan đến model User sẽ tự động thêm điều kiện where('active', 1).

4. Xoá Global Scopes

Nếu bạn muốn loại bỏ một global scope khỏi một truy vấn cụ thể, bạn có thể sử dụng phương thức withoutGlobalScope.

Ví dụ:
$users = User::withoutGlobalScope(ActiveScope::class)->get();

Lệnh này sẽ loại bỏ scope ActiveScope và trả về tất cả người dùng, kể cả những người dùng chưa kích hoạt.

Lợi ích của Eloquent Query Scopes

  1. Tái sử dụng: Các scope giúp bạn tránh lặp lại mã bằng cách gom nhóm các điều kiện truy vấn chung vào một nơi có thể tái sử dụng.
  2. Tăng tính rõ ràng: Sử dụng scopes giúp mã nguồn dễ đọc hơn và rõ ràng hơn, đặc biệt là khi truy vấn phức tạp.
  3. Dễ bảo trì: Khi cần thay đổi một điều kiện truy vấn, bạn chỉ cần thay đổi trong scope và tất cả các truy vấn khác sẽ tự động cập nhật theo.

Kết luận

Eloquent Query Scopes là một công cụ tuyệt vời giúp bạn tối ưu hoá và tổ chức mã nguồn của mình. Bằng cách sử dụng Local Scopes, Dynamic Scopes và Global Scopes, bạn có thể dễ dàng tái sử dụng các truy vấn phức tạp và giữ cho mã nguồn của mình ngắn gọn, dễ bảo trì.

Eloquent: Factories (P2)

Eloquent: Factories (P2)

01.08.2024
Author: ADMIN

bài trước, chúng ta đã nắm sơ bộ về Eloquent Factories rồi, tiếp theo, chúng ta cùng tìm hiểu tiếp các Relationships trong Factories nhé.

# Many to Many Relationships

Laravel cung cấp nhiều cách để xây dựng và quản lý các mối quan hệ giữa các mô hình bằng cách sử dụng factories. Dưới đây là hướng dẫn chi tiết về các loại mối quan hệ khác nhau và cách sử dụng factories để tạo chúng.

1. Quan Hệ Many-to-Many

Khi hai mô hình có mối quan hệ nhiều-mối quan hệ, bạn có thể sử dụng phương thức hasAttached của factory để liên kết chúng qua bảng pivot.

Tạo Mô Hình Với Mối Quan Hệ Many-to-Many

Giả sử bạn có mô hình UserRole, và bạn muốn tạo một người dùng với ba vai trò:

use App\Models\Role;
use App\Models\User;
 
$user = User::factory()
            ->hasAttached(
                Role::factory()->count(3),
                ['active' => true]  // Thuộc tính trên bảng pivot
            )
            ->create();

Sử Dụng Closure Để Thay Đổi Trạng Thái

Nếu trạng thái cần truy cập mô hình liên quan, bạn có thể sử dụng closure:

$user = User::factory()
            ->hasAttached(
                Role::factory()
                    ->count(3)
                    ->state(function (array $attributes, User $user) {
                        return ['name' => $user->name.' Role'];
                    }),
                ['active' => true]
            )
            ->create();

Sử Dụng Các Mô Hình Hiện Có

Nếu bạn đã có các mô hình để liên kết, bạn có thể truyền chúng vào phương thức hasAttached:

$roles = Role::factory()->count(3)->create();
 
$user = User::factory()
            ->count(3)
            ->hasAttached($roles, ['active' => true])
            ->create();

Sử Dụng Các Phương Thức "Magic"

Để tiện lợi, bạn có thể sử dụng phương thức "ma thuật" để tạo quan hệ nhiều-mối quan hệ:

$user = User::factory()
            ->hasRoles(1, [
                'name' => 'Editor'
            ])
            ->create();

# Quan Hệ "Đa Hình" (Polymorphic Relationships)

Các quan hệ đa hình có thể được tạo bằng factories như các quan hệ bình thường.

Quan Hệ Morph Many

Nếu mô hình Post có mối quan hệ morphMany với mô hình Comment:

use App\Models\Post;
 
$post = Post::factory()->hasComments(3)->create();

Morph To Relationships

Để tạo các quan hệ morphTo, bạn không thể sử dụng các phương thức "ma thuật". Thay vào đó, bạn sử dụng phương thức for:

$comments = Comment::factory()->count(3)->for(
    Post::factory(), 'commentable'
)->create();

Quan Hệ "Many-to-Many" Đa Hình

Quan hệ nhiều-mối quan hệ đa hình có thể được tạo giống như các quan hệ nhiều-mối quan hệ không phải đa hình:

use App\Models\Tag;
use App\Models\Video;
 
$videos = Video::factory()
            ->hasAttached(
                Tag::factory()->count(3),
                ['public' => true]
            )
            ->create();

Bạn cũng có thể sử dụng phương thức "ma thuật":

$videos = Video::factory()
            ->hasTags(3, ['public' => true])
            ->create();

Định Nghĩa Quan Hệ Trong Factory

Để định nghĩa một mối quan hệ trong factory của mô hình, bạn thường gán một instance factory mới cho khóa ngoại của mối quan hệ.

Định Nghĩa Quan Hệ "Belongs To"

Ví dụ, nếu bạn muốn tạo một người dùng mới khi tạo một bài viết, bạn có thể làm như sau:

use App\Models\User;
 
/**
 * Định nghĩa trạng thái mặc định của mô hình.
 *
 * @return array<string, mixed>
 */
public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}

Sử Dụng Closure Để Định Nghĩa Trạng Thái

Nếu các cột của mối quan hệ phụ thuộc vào factory định nghĩa nó, bạn có thể gán một closure cho thuộc tính:

public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'user_type' => function (array $attributes) {
            return User::find($attributes['user_id'])->type;
        },
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}

Tái Sử Dụng Một Mô Hình Đã Tạo

Nếu bạn có các mô hình chia sẻ một mối quan hệ chung với một mô hình khác, bạn có thể sử dụng phương thức recycle để đảm bảo một instance của mô hình liên quan được tái sử dụng cho tất cả các mối quan hệ được tạo bởi factory.

Tái Sử Dụng Một Mô Hình Để Liên Kết

Ví dụ, nếu bạn có các mô hình Airline, Flight, và Ticket, và bạn muốn đảm bảo rằng cùng một hãng hàng không được sử dụng cho cả vé và chuyến bay, bạn có thể làm như sau:

Ticket::factory()
    ->recycle(Airline::factory()->create())
    ->create();

Tái Sử Dụng Một Bộ Sưu Tập Mô Hình

Bạn cũng có thể truyền một bộ sưu tập mô hình vào phương thức recycle. Khi có bộ sưu tập, một mô hình ngẫu nhiên từ bộ sưu tập sẽ được chọn khi factory cần một mô hình loại đó:

$airlines = Airline::factory()->count(3)->create();

Ticket::factory()
    ->recycle($airlines)
    ->create();

Tóm Tắt

  • Quan Hệ Nhiều-Mối Quan Hệ: Sử dụng hasAttached để liên kết các mô hình qua bảng pivot và phương thức "ma thuật" để đơn giản hóa việc định nghĩa mối quan hệ.

  • Quan Hệ Đa Hình: Tạo các quan hệ morphManymorphTo như các quan hệ bình thường, và sử dụng phương thức for cho morphTo.

  • Định Nghĩa Quan Hệ Trong Factory: Gán một instance factory mới cho khóa ngoại và sử dụng closure nếu cần.

  • Tái Sử Dụng Một Mô Hình Đã Tạo: Sử dụng phương thức recycle để đảm bảo tái sử dụng một mô hình cho tất cả các mối quan hệ liên quan.

Những tính năng này giúp bạn dễ dàng tạo và quản lý dữ liệu mẫu cho các mối quan hệ phức tạp trong ứng dụng của bạn.

Eloquent: Factories

Eloquent: Factories

01.08.2024
Author: ADMIN

Ở phần trước các bạn đã được tiếp xúc cơ bản với Eloquent Model and MVC. Trong bài viết này, chúng ta cùng tìm hiểu thêm về Factories nhé!

Factories trong Laravel giúp tạo ra các mô hình (model) và các bản ghi trong cơ sở dữ liệu một cách dễ dàng và tự động, giúp việc kiểm thử và phát triển trở nên thuận tiện hơn.

Tạo Factory

Để tạo một factory, bạn có thể sử dụng lệnh artisan make:factory. Ví dụ, để tạo một factory cho mô hình User, bạn có thể chạy lệnh:

php artisan make:factory UserFactory

Lệnh này sẽ tạo một file factory trong thư mục database/factories.

Định Nghĩa Factory

Trong file factory mới tạo, bạn sẽ định nghĩa các giá trị mặc định cho các thuộc tính của mô hình. Ví dụ:

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    protected $model = User::class;

    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => bcrypt('password'), // password mặc định
            'remember_token' => Str::random(10),
        ];
    }
}

Sử Dụng Factory

Sau khi đã định nghĩa xong factory, bạn có thể sử dụng nó để tạo ra các bản ghi trong cơ sở dữ liệu. Bạn có thể sử dụng phương thức create để lưu bản ghi vào cơ sở dữ liệu hoặc make để chỉ tạo ra đối tượng mà không lưu.

// Tạo một người dùng và lưu vào cơ sở dữ liệu
$user = User::factory()->create();

// Tạo một đối tượng người dùng nhưng không lưu vào cơ sở dữ liệu
$user = User::factory()->make();

Bạn cũng có thể tạo nhiều bản ghi cùng lúc bằng cách truyền vào số lượng cần tạo:

// Tạo 5 người dùng và lưu vào cơ sở dữ liệu
$users = User::factory()->count(5)->create();

Sử Dụng Factory Với Seeder

Factories rất hữu ích khi sử dụng kết hợp với seeders để tạo dữ liệu mẫu cho ứng dụng:

use Illuminate\Database\Seeder;
use App\Models\User;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        // Tạo 50 người dùng
        User::factory()->count(50)->create();
    }
}

Chạy lệnh seeder:

php artisan db:seed

# Model and Factory Discovery Conventions

Trong Laravel, các model và factory được kết nối với nhau qua các quy tắc phát hiện (discovery conventions). Khi bạn sử dụng trait Illuminate\Database\Eloquent\Factories\HasFactory trong mô hình của bạn, Laravel sẽ tự động tìm và sử dụng factory phù hợp theo các quy tắc sau:

  1. Tự Động Phát Hiện Factory:

    • Laravel sẽ tìm kiếm một factory trong namespace Database\Factories mà có tên lớp (class name) khớp với tên mô hình (model name) và kết thúc bằng Factory.
    • Ví dụ, nếu bạn có mô hình Flight, Laravel sẽ tìm kiếm một factory có tên FlightFactory trong namespace Database\Factories.
  2. Xác Định Factory Cụ Thể:

    • Nếu bạn muốn xác định factory cho mô hình của bạn theo cách cụ thể hơn hoặc nếu tên và namespace của factory không tuân theo quy tắc tự động, bạn có thể ghi đè phương thức newFactory trên mô hình của mình để trả về instance của factory tương ứng.

Ví Dụ

Giả sử bạn có mô hình Flight và factory tương ứng FlightFactory:

  1. Tạo Mô Hình và Factory:

    • Mô hình Flight:
      namespace App\Models;
      
      use Illuminate\Database\Eloquent\Factories\HasFactory;
      use Illuminate\Database\Eloquent\Model;
      
      class Flight extends Model
      {
          use HasFactory;
      
          // Bạn có thể tùy chỉnh phương thức newFactory nếu cần
          protected static function newFactory()
          {
              return \Database\Factories\FlightFactory::new();
          }
      }
      
    • Factory FlightFactory:
      namespace Database\Factories;
      
      use App\Models\Flight;
      use Illuminate\Database\Eloquent\Factories\Factory;
      
      class FlightFactory extends Factory
      {
          /**
           * Tên của mô hình mà factory tương ứng.
           *
           * @var class-string<\Illuminate\Database\Eloquent\Model>
           */
          protected $model = Flight::class;
      
          /**
           * Định nghĩa các thuộc tính mẫu cho mô hình.
           *
           * @return array
           */
          public function definition()
          {
              return [
                  'flight_number' => $this->faker->unique()->word,
                  'departure' => $this->faker->dateTime,
                  'arrival' => $this->faker->dateTime,
              ];
          }
      }
      
  2. Sử Dụng Factory Trong Seeder:
    Khi bạn sử dụng factory trong seeder, bạn có thể dễ dàng tạo dữ liệu mẫu:
    use Illuminate\Database\Seeder;
    use App\Models\Flight;
    
    class DatabaseSeeder extends Seeder
    {
        public function run()
        {
            // Tạo 10 bản ghi flight
            Flight::factory()->count(10)->create();
        }
    }
    
  3. Chạy Seeder:
    php artisan db:seed
    

# Factory States

Factory states trong Laravel cho phép bạn định nghĩa các trạng thái (states) khác nhau để áp dụng các thay đổi cụ thể cho các mô hình khi tạo dữ liệu mẫu. Điều này rất hữu ích khi bạn muốn có các biến thể của mô hình với các thuộc tính khác nhau mà không cần phải viết nhiều factory khác nhau.

Cách Định Nghĩa và Sử Dụng Các Trạng Thái Trong Factory

  1. Định Nghĩa Trạng Thái:

    Bạn có thể định nghĩa trạng thái trong factory bằng cách sử dụng phương thức state. Phương thức này nhận một closure mà sẽ nhận các thuộc tính gốc của factory và trả về các thuộc tính đã được thay đổi.

    Ví dụ:

    Giả sử bạn có một factory cho mô hình User và bạn muốn định nghĩa một trạng thái suspended để thay đổi thuộc tính account_status thành suspended:

    namespace Database\Factories;
    
    use App\Models\User;
    use Illuminate\Database\Eloquent\Factories\Factory;
    
    class UserFactory extends Factory
    {
        /**
         * Tên của mô hình mà factory tương ứng.
         *
         * @var class-string<\Illuminate\Database\Eloquent\Model>
         */
        protected $model = User::class;
    
        /**
         * Định nghĩa các thuộc tính mẫu cho mô hình.
         *
         * @return array
         */
        public function definition()
        {
            return [
                'name' => $this->faker->name,
                'email' => $this->faker->unique()->safeEmail,
                'password' => bcrypt('password'),
                'account_status' => 'active',  // Giá trị mặc định
            ];
        }
    
        /**
         * Chỉ định rằng người dùng bị tạm ngưng.
         *
         * @return \Illuminate\Database\Eloquent\Factories\Factory
         */
        public function suspended(): Factory
        {
            return $this->state(function (array $attributes) {
                return [
                    'account_status' => 'suspended',
                ];
            });
        }
    }
    
  2. Sử Dụng Các Trạng Thái:

    Khi bạn muốn sử dụng một trạng thái cụ thể khi tạo dữ liệu mẫu, bạn có thể gọi phương thức trạng thái đó trước khi gọi create() hoặc make().

    Ví dụ:

    // Tạo một người dùng với trạng thái bị tạm ngưng
    $suspendedUser = User::factory()->suspended()->create();
    
    // Tạo một người dùng với trạng thái mặc định
    $activeUser = User::factory()->create();
    
  3. Trạng Thái "Trashed":

    Nếu mô hình Eloquent của bạn hỗ trợ xóa mềm (soft deletes), bạn có thể sử dụng trạng thái trashed được tích hợp sẵn để chỉ định rằng mô hình đã bị "xóa mềm".

    Ví dụ:

    use App\Models\User;
    
    // Tạo một người dùng đã bị xóa mềm
    $trashedUser = User::factory()->trashed()->create();
    
    Trạng thái trashed tự động có sẵn cho tất cả các factory mà mô hình hỗ trợ xóa mềm. Bạn không cần phải định nghĩa trạng thái này trong factory của mình.

# Tạo Mô Hình Sử Dụng Factory

Khi bạn đã định nghĩa các factory, bạn có thể sử dụng phương thức factory tĩnh được cung cấp bởi trait Illuminate\Database\Eloquent\Factories\HasFactory trong các mô hình của bạn để khởi tạo các phiên bản factory cho mô hình đó. Dưới đây là hướng dẫn chi tiết về cách tạo mô hình sử dụng factory.

Khởi Tạo Mô Hình

  1. Tạo Mô Hình Mà Không Lưu Vào Cơ Sở Dữ Liệu:

    Để tạo các mô hình mà không lưu vào cơ sở dữ liệu, bạn có thể sử dụng phương thức make:

    use App\Models\User;
    
    $user = User::factory()->make();
    

    Phương thức này tạo ra một đối tượng User mới nhưng không lưu vào cơ sở dữ liệu.

  2. Tạo Một Bộ Sưu Tập Các Mô Hình:

    Bạn có thể tạo một số lượng mô hình nhất định bằng cách sử dụng phương thức count:

    $users = User::factory()->count(3)->make();
    

    Lệnh trên tạo ra ba đối tượng User mà không lưu chúng vào cơ sở dữ liệu.

Áp Dụng Trạng Thái

Bạn có thể áp dụng các trạng thái khác nhau cho các mô hình. Nếu bạn muốn áp dụng nhiều trạng thái cho các mô hình, bạn chỉ cần gọi các phương thức trạng thái trực tiếp:

$users = User::factory()->count(5)->suspended()->make();

Trong ví dụ này, năm đối tượng User được tạo ra với trạng thái bị tạm ngưng.

Ghi Đè Thuộc Tính

Nếu bạn muốn ghi đè một số giá trị mặc định của mô hình, bạn có thể truyền một mảng các giá trị vào phương thức make. Chỉ những thuộc tính được chỉ định mới bị thay đổi, trong khi các thuộc tính khác vẫn giữ giá trị mặc định:

$user = User::factory()->make([
    'name' => 'Abigail Otwell',
]);

Ngoài ra, bạn có thể sử dụng phương thức state để thực hiện việc ghi đè thuộc tính trực tiếp:

$user = User::factory()->state([
    'name' => 'Abigail Otwell',
])->make();

Lưu ý rằng việc tạo mô hình bằng factory tự động tắt bảo vệ gán hàng loạt (mass assignment).

Lưu Mô Hình Vào Cơ Sở Dữ Liệu

Phương thức create không chỉ khởi tạo mô hình mà còn lưu nó vào cơ sở dữ liệu:

use App\Models\User;

// Tạo một đối tượng User và lưu vào cơ sở dữ liệu...
$user = User::factory()->create();

// Tạo ba đối tượng User và lưu vào cơ sở dữ liệu...
$users = User::factory()->count(3)->create();

Bạn có thể ghi đè các thuộc tính mặc định của factory bằng cách truyền một mảng các thuộc tính vào phương thức create:

$user = User::factory()->create([
    'name' => 'Abigail',
]);

Sequences

Đôi khi bạn muốn luân phiên giá trị của một thuộc tính mô hình cho mỗi mô hình được tạo. Bạn có thể thực hiện điều này bằng cách định nghĩa một chuỗi (sequence) trong factory. Ví dụ, bạn có thể muốn luân phiên giá trị của thuộc tính admin giữa Y và N:

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
                ->count(10)
                ->state(new Sequence(
                    ['admin' => 'Y'],
                    ['admin' => 'N'],
                ))
                ->create();

Trong ví dụ này, năm đối tượng User sẽ có giá trị admin là Y và năm đối tượng sẽ có giá trị là N.

Nếu cần, bạn có thể sử dụng một closure làm giá trị chuỗi. Closure sẽ được gọi mỗi khi chuỗi cần một giá trị mới:

use Illuminate\Database\Eloquent\Factories\Sequence;

$users = User::factory()
                ->count(10)
                ->state(new Sequence(
                    fn (Sequence $sequence) => ['role' => UserRoles::all()->random()],
                ))
                ->create();

Trong closure của chuỗi, bạn có thể truy cập các thuộc tính $index hoặc $count trên đối tượng chuỗi được chèn vào closure. Thuộc tính $index chứa số lần lặp qua chuỗi cho đến thời điểm đó, trong khi thuộc tính $count chứa tổng số lần chuỗi sẽ được gọi:

$users = User::factory()
                ->count(10)
                ->sequence(fn (Sequence $sequence) => ['name' => 'Name '.$sequence->index])
                ->create();

Để tiện lợi, bạn cũng có thể áp dụng chuỗi bằng phương thức sequence, phương thức này thực hiện gọi phương thức state nội bộ. Phương thức sequence chấp nhận một closure hoặc các mảng thuộc tính được chuỗi hóa:

$users = User::factory()
                ->count(2)
                ->sequence(
                    ['name' => 'First User'],
                    ['name' => 'Second User'],
                )
                ->create();

# Factory Relationships

Trong Laravel, bạn có thể xây dựng các mối quan hệ giữa các mô hình bằng cách sử dụng các phương thức factory. Dưới đây là cách bạn có thể sử dụng factories để tạo các mối quan hệ hasManybelongsTo giữa các mô hình.

Quan Hệ "Has Many"

Khi một mô hình có nhiều mối quan hệ với một mô hình khác, ví dụ như một User có nhiều Post, bạn có thể sử dụng phương thức has của factory để tạo các mô hình liên quan.

  1. Tạo Mô Hình Có Quan Hệ Has Many

    Giả sử bạn có mô hình UserPost, và mô hình User định nghĩa một mối quan hệ hasMany với Post. Để tạo một người dùng với ba bài viết, bạn có thể sử dụng phương thức has như sau:

    use App\Models\Post;
    use App\Models\User;
    
    $user = User::factory()
                ->has(Post::factory()->count(3))
                ->create();
    

    Laravel sẽ tự động giả định rằng mô hình User có một phương thức posts để định nghĩa mối quan hệ hasMany. Nếu cần, bạn có thể chỉ định tên của mối quan hệ:

    $user = User::factory()
                ->has(Post::factory()->count(3), 'posts')
                ->create();
    
  2. Sử Dụng Các Phương Thức "Ma Thuật"

    Để tiện lợi, bạn có thể sử dụng các phương thức mối quan hệ "ma thuật" của factory. Ví dụ, phương thức sau sẽ tự động xác định rằng các mô hình liên quan nên được tạo thông qua phương thức posts trên mô hình User:

    $user = User::factory()
                ->hasPosts(3)
                ->create();
    

    Bạn cũng có thể ghi đè thuộc tính cho các mô hình liên quan:

    $user = User::factory()
                ->hasPosts(3, [
                    'published' => false,
                ])
                ->create();
    

    Và bạn có thể sử dụng closure nếu trạng thái cần truy cập vào mô hình cha:

    $user = User::factory()
                ->hasPosts(3, function (array $attributes, User $user) {
                    return ['user_type' => $user->type];
                })
                ->create();
    

Quan Hệ "Belongs To"

Bây giờ, hãy khám phá cách xây dựng các mối quan hệ ngược lại, tức là khi một mô hình thuộc về một mô hình khác. Bạn có thể sử dụng phương thức for để định nghĩa mô hình cha mà các mô hình do factory tạo ra thuộc về.

  1. Tạo Các Mô Hình Thuộc Về Một Mô Hình Cha

    Để tạo ba bài viết thuộc về một người dùng duy nhất, bạn có thể làm như sau:

    use App\Models\Post;
    use App\Models\User;
    
    $posts = Post::factory()
                ->count(3)
                ->for(User::factory()->state([
                    'name' => 'Jessica Archer',
                ]))
                ->create();
    

    Nếu bạn đã có một đối tượng mô hình cha và muốn liên kết với các mô hình bạn đang tạo, bạn có thể truyền đối tượng mô hình vào phương thức for:

    $user = User::factory()->create();
    
    $posts = Post::factory()
                ->count(3)
                ->for($user)
                ->create();
    
  2. Sử Dụng Các Phương Thức "Ma Thuật"

    Để tiện lợi, bạn cũng có thể sử dụng các phương thức mối quan hệ "ma thuật" của factory để định nghĩa quan hệ belongsTo. Ví dụ, phương thức sau sẽ tự động xác định rằng các bài viết nên thuộc về mối quan hệ user trên mô hình Post:

    $posts = Post::factory()
                ->count(3)
                ->forUser([
                    'name' => 'Jessica Archer',
                ])
                ->create();
    

Tóm Tắt

  • Quan Hệ "Has Many": Sử dụng phương thức has để tạo các mô hình liên quan với mối quan hệ hasMany. Bạn có thể áp dụng trạng thái và sử dụng các phương thức "ma thuật" để dễ dàng định nghĩa mối quan hệ.

  • Quan Hệ "Belongs To": Sử dụng phương thức for để xác định mô hình cha mà các mô hình do factory tạo ra thuộc về. Bạn cũng có thể sử dụng các phương thức "ma thuật" để đơn giản hóa việc định nghĩa quan hệ.

Các tính năng này giúp bạn dễ dàng tạo dữ liệu mẫu cho việc kiểm thử và phát triển ứng dụng với các mối quan hệ giữa các mô hình.

Ở bài tiếp theo, chúng ta sẽ cùng khám phá các Relationships và các vấn đề liên quan đến Factories nhé

Middleware

Middleware

01.08.2024
Author: ADMIN

Middleware cung cấp một cơ chế lọc các yêu cầu HTTP vào ứng dụng của bạn. Ví dụ, Laravel bao gồm một middleware kiểm tra người dùng của bạn có xác thực hay chưa. Nếu người dùng không xác thực, middleware sẽ chuyển hướng người dùng đến trang đăng nhập. Tuy nhiên, nếu người dùng đã xác thực, middleware sẽ cho phép yêu cầu tiếp tục vào ứng dụng.

Dưới đây là các bước để định nghĩa middleware trong Laravel:

1. Tạo Middleware

Để tạo middleware, bạn có thể sử dụng lệnh Artisan sau:

php artisan make:middleware CheckAge

Lệnh này sẽ tạo ra một lớp middleware mới tại app/Http/Middleware/CheckAge.php. Trong lớp middleware này, bạn chỉ cần định nghĩa phương thức handle.

2. Định nghĩa Middleware

Trong lớp middleware, bạn có thể viết logic để kiểm tra hoặc xử lý yêu cầu. Ví dụ, dưới đây là cách middleware kiểm tra độ tuổi của người dùng:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}

Trong ví dụ này, nếu độ tuổi của người dùng nhỏ hơn hoặc bằng 200, middleware sẽ chuyển hướng họ về trang chủ. Nếu không, yêu cầu sẽ tiếp tục được xử lý.

3. Đăng ký Middleware

Sau khi tạo middleware, bạn cần đăng ký nó trong ứng dụng. Có hai cách để đăng ký middleware: toàn cục và nhóm.

3.1. Middleware Global

Để đăng ký middleware toàn cục, bạn thêm nó vào thuộc tính $middleware trong app/Http/Kernel.php:

protected $middleware = [
    // Other middleware
    \App\Http\Middleware\CheckAge::class,
];
3.2. Middleware Groups

Để đăng ký middleware nhóm, bạn thêm nó vào thuộc tính $middlewareGroups trong app/Http/Kernel.php. Ví dụ, bạn có thể thêm middleware vào nhóm web:

protected $middlewareGroups = [
    'web' => [
        // Other middleware
        \App\Http\Middleware\CheckAge::class,
    ],

    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];
3.3. Middleware Định Tuyến

Bạn có thể gán middleware cho các tuyến cụ thể bằng cách sử dụng phương thức middleware trong file routes/web.php hoặc routes/api.php:

Route::get('admin/profile', function () {
    // Only authenticated users may enter...
})->middleware('auth', 'check.age');

4. Middleware Tham Số

Middleware cũng có thể chấp nhận tham số. Ví dụ, bạn có thể tạo middleware để kiểm tra vai trò của người dùng:

public function handle($request, Closure $next, $role)
{
    if (! $request->user()->hasRole($role)) {
        // Redirect...
    }

    return $next($request);
}

Sau đó, bạn có thể gán middleware này cho một tuyến với tham số:

Route::put('post/{id}', function ($id) {
    // Update the post...
})->middleware('role:editor');

# Middleware and Responses

Middleware có thể thực hiện các tác vụ trước hoặc sau khi chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng. Ví dụ, middleware sau đây sẽ thực hiện một số tác vụ trước khi yêu cầu được xử lý bởi ứng dụng:

Ví dụ Middleware

Dưới đây là một ví dụ về middleware thực hiện một số tác vụ trước khi xử lý yêu cầu:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class BeforeMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // Thực hiện một số tác vụ trước khi yêu cầu được xử lý
        // Ví dụ: kiểm tra điều kiện hoặc ghi log
        if ($request->user() && $request->user()->isBlocked()) {
            return response('Your account is blocked.', 403);
        }

        // Chuyển tiếp yêu cầu vào sâu hơn trong ứng dụng
        return $next($request);
    }
}

Thực hiện tác vụ sau khi xử lý yêu cầu

Middleware cũng có thể thực hiện các tác vụ sau khi yêu cầu đã được xử lý. Để làm điều này, bạn chỉ cần thêm logic sau khi gọi hàm $next($request):

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AfterMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        // Xử lý yêu cầu
        $response = $next($request);

        // Thực hiện một số tác vụ sau khi yêu cầu đã được xử lý
        // Ví dụ: thêm header vào phản hồi
        $response->header('X-Header-One', 'Header Value');

        return $response;
    }
}

Trong ví dụ trên, middleware sẽ thêm một header vào phản hồi sau khi yêu cầu đã được xử lý bởi ứng dụng.

# Sorting Middleware

Trong Laravel, bạn có thể chỉ định thứ tự thực hiện của các middleware. Việc sắp xếp này có thể hữu ích khi bạn cần một middleware phải được thực thi trước hoặc sau một middleware khác. Laravel cung cấp một cách dễ dàng để sắp xếp thứ tự của các middleware thông qua thuộc tính $middlewarePriority trong lớp App\Http\Kernel.

Định nghĩa Thứ Tự Middleware

Để sắp xếp thứ tự thực hiện của middleware, bạn chỉ cần thêm thuộc tính $middlewarePriority vào lớp App\Http\Kernel và liệt kê các middleware theo thứ tự bạn muốn chúng được thực thi:

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        // Danh sách các middleware toàn cục
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            // Danh sách các middleware nhóm 'web'
        ],

        'api' => [
            // Danh sách các middleware nhóm 'api'
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        // Danh sách các route middleware
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \App\Http\Middleware\FirstMiddleware::class,
        \App\Http\Middleware\SecondMiddleware::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\AnotherMiddleware::class,
        // Thêm các middleware khác theo thứ tự bạn muốn
    ];
}

Trong ví dụ trên, FirstMiddleware sẽ được thực thi trước SecondMiddleware, và AnotherMiddleware sẽ được thực thi sau StartSessionShareErrorsFromSession.

Ví Dụ Về Middleware

Dưới đây là ví dụ về hai middleware mà bạn muốn sắp xếp thứ tự thực hiện:

  1. FirstMiddleware:

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class FirstMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            // Logic của FirstMiddleware
            return $next($request);
        }
    }
    
  2. SecondMiddleware:
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class SecondMiddleware
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            // Logic của SecondMiddleware
            return $next($request);
        }
    }
    

Kết Hợp Với Route

Sau khi định nghĩa thứ tự của middleware, bạn có thể gán chúng cho các tuyến hoặc nhóm tuyến trong tệp routes/web.php hoặc routes/api.php:

// routes/web.php

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', 'HomeController@index');
});

// Hoặc sử dụng trực tiếp trong các tuyến:
Route::get('/example', 'ExampleController@index')->middleware('first', 'second');

# Terminable Middleware

Trong Laravel, middleware có thể được chia thành hai loại chính: middleware thực thi trong quá trình xử lý yêu cầu và middleware thực thi sau khi phản hồi đã được gửi đến client. Middleware thuộc loại thứ hai được gọi là "terminable middleware".

Terminable middleware cho phép bạn thực hiện các công việc sau khi phản hồi đã được gửi về phía client, chẳng hạn như ghi log hoặc thực hiện các tác vụ tốn thời gian mà bạn không muốn làm chậm thời gian phản hồi của ứng dụng.

Tạo Middleware Terminable

Để tạo một terminable middleware, bạn cần tạo một middleware như bình thường và thêm phương thức terminate vào lớp middleware đó. Phương thức terminate sẽ được tự động gọi sau khi phản hồi đã được gửi về phía client.

  1. Tạo Middleware bằng Artisan:
    php artisan make:middleware LogAfterRequest
    
  2. Định nghĩa Middleware với phương thức terminate:
    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Symfony\Component\HttpFoundation\Response;
    
    class LogAfterRequest
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle(Request $request, Closure $next)
        {
            // Thực hiện các công việc trước khi xử lý yêu cầu
            return $next($request);
        }
    
        /**
         * Handle tasks after the response has been sent to the client.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Symfony\Component\HttpFoundation\Response  $response
         * @return void
         */
        public function terminate(Request $request, Response $response)
        {
            // Thực hiện các công việc sau khi phản hồi đã được gửi đến client
            \Log::info('Request has been completed.');
        }
    }
    

Đăng Ký Middleware

Bạn cần đăng ký middleware trong tệp app/Http/Kernel.php để Laravel có thể nhận diện và sử dụng middleware đó:

  1. Thêm middleware vào thuộc tính $middleware hoặc $routeMiddleware của lớp Kernel:
    // app/Http/Kernel.php
    
    protected $middleware = [
        // Các middleware khác
        \App\Http\Middleware\LogAfterRequest::class,
    ];
    
  2. Nếu bạn muốn middleware này chỉ áp dụng cho một số tuyến cụ thể, bạn có thể thêm vào thuộc tính $routeMiddleware:
    // app/Http/Kernel.php
    
    protected $routeMiddleware = [
        // Các route middleware khác
        'log.after' => \App\Http\Middleware\LogAfterRequest::class,
    ];
    
  3. Sử dụng middleware trong tuyến của bạn:
    // routes/web.php
    
    Route::get('/example', 'ExampleController@index')->middleware('log.after');
    

Kết Hợp với Các Tác Vụ Sau Phản Hồi

Bạn có thể sử dụng terminable middleware để thực hiện các tác vụ sau khi phản hồi đã được gửi đến client, chẳng hạn như:

  • Ghi log các yêu cầu và phản hồi
  • Gửi email
  • Thực hiện các tác vụ bảo trì
  • Đặt lại các kết nối hoặc phiên làm việc

Ví dụ, bạn có thể sử dụng phương thức terminate để ghi lại log các thông tin về yêu cầu và phản hồi:

public function terminate(Request $request, Response $response)
{
    \Log::info('Request URL: ' . $request->fullUrl());
    \Log::info('Response Status: ' . $response->status());
}
Routing

Routing

01.08.2024
Author: ADMIN

# Basic Routing

1. Khái niệm về Route

Route trong Laravel là cách bạn định nghĩa URL cho ứng dụng của mình. Route giúp bạn chỉ định URL nào sẽ gọi đến Controller nào hoặc thực hiện hành động gì.

2. Định nghĩa Route Cơ Bản

Tất cả các route của Laravel được định nghĩa trong các file nằm trong thư mục routes. Các file này được tự động tải bởi App\Providers\RouteServiceProvider của ứng dụng của bạn. Có bốn file route chính:

  • web.php: Định nghĩa các route cho web application.
  • api.php: Định nghĩa các route cho API.
  • console.php: Định nghĩa các route cho console commands.
  • channels.php: Định nghĩa các route cho event broadcasting channels.

Định nghĩa route trong web.php

Dưới đây là một ví dụ đơn giản về cách định nghĩa một route trong file web.php:

Route::get('/', function () {
    return view('welcome');
});

Trong ví dụ trên:

  • Route::get('/'): Định nghĩa một route sử dụng phương thức GET cho URL /.
  • function () { return view('welcome'); }: Định nghĩa hành động sẽ thực hiện khi người dùng truy cập vào URL /. Ở đây, Laravel sẽ trả về view welcome.

3. Các Phương Thức Route

Laravel hỗ trợ nhiều phương thức HTTP khác nhau, bao gồm:

  • GET: Dùng để truy xuất dữ liệu từ server.
  • POST: Dùng để gửi dữ liệu lên server.
  • PUT: Dùng để cập nhật dữ liệu trên server.
  • PATCH: Dùng để cập nhật một phần tài nguyên trên server. Tương tự như PUT nhưng chỉ cập nhật các phần cụ thể của tài nguyên.
  • DELETE: Dùng để xóa dữ liệu từ server.
  • OPTIONS: Dùng để truy vấn các phương thức HTTP mà server hỗ trợ cho một URL cụ thể. Thường được sử dụng trong các ứng dụng RESTful API để kiểm tra các tùy chọn giao tiếp.

Ví dụ về các phương thức khác nhau:

Route::get('/products', function () {
    return 'Get all products';
});

Route::post('/products', function () {
    return 'Create a new product';
});

Route::put('/products/{id}', function ($id) {
    return 'Update the product with ID ' . $id;
});

Route::patch('/products/{id}', function ($id) {
    return 'Partially update the product with ID ' . $id;
});

Route::delete('/products/{id}', function ($id) {
    return 'Delete the product with ID ' . $id;
});

Route::options('/products', function () {
    return response()->json(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
});

4. Route với Tham Số

Bạn có thể định nghĩa route có tham số như sau:

Route::get('/user/{id}', function ($id) {
    return 'User '.$id;
});

Trong ví dụ này, {id} là một tham số động. Khi người dùng truy cập vào URL user/1, Laravel sẽ gán giá trị 1 vào biến $id và trả về User 1.

5. Route Groups

Bạn có thể nhóm các route lại với nhau bằng cách sử dụng Route::group. Điều này giúp bạn dễ dàng áp dụng middleware hoặc tiền tố URL cho một nhóm route.

Route::group(['prefix' => 'admin'], function () {
    Route::get('/users', function () {
        // Matches The "/admin/users" URL
    });

    Route::get('/settings', function () {
        // Matches The "/admin/settings" URL
    });
});

Trong ví dụ trên, tất cả các route trong nhóm này sẽ có tiền tố admin.

6. Middleware

Middleware là các lớp trung gian mà HTTP request phải đi qua trước khi đến Controller. Bạn có thể áp dụng middleware cho route như sau:

Route::get('/profile', function () {
    // Only authenticated users may enter...
})->middleware('auth');

Trong ví dụ này, middleware auth sẽ kiểm tra xem người dùng có được xác thực hay không trước khi cho phép truy cập vào route /profile.

Laravel cung cấp hai nhóm middleware chính cho các file route:

  • web middleware group: Được áp dụng cho các route trong routes/web.php. Middleware nhóm này bao gồm các tính năng như:
    • Session state
    • CSRF protection
    • Cookie encryption
    • ...
  • api middleware group: Được áp dụng cho các route trong routes/api.php. Middleware nhóm này bao gồm các tính năng như:
    • Stateless (không trạng thái)
    • Token-based authentication
    • Rate limiting
    • ...

7. CSRF Protection

Hãy nhớ rằng, bất kỳ biểu mẫu HTML nào trỏ tới các route sử dụng phương thức POST, PUT, PATCH, hoặc DELETE được định nghĩa trong file route web cần phải bao gồm trường token CSRF. Nếu không, yêu cầu sẽ bị từ chối. Bạn có thể đọc thêm về bảo vệ CSRF trong tài liệu CSRF:

<form method="POST" action="/profile">
    @csrf
    <!-- Các trường input khác -->
    <button type="submit">Submit</button>
</form>

Việc bảo vệ CSRF rất quan trọng để ngăn chặn các tấn công giả mạo yêu cầu từ trang chéo, đảm bảo rằng các yêu cầu tới server đến từ nguồn đáng tin cậy.

8. Redirect Routes

Nếu bạn định nghĩa một route để chuyển hướng đến một URI khác, bạn có thể sử dụng phương thức Route::redirect. Phương thức này cung cấp một cách tắt thuận tiện để bạn không phải định nghĩa một route hoặc controller đầy đủ cho việc thực hiện chuyển hướng đơn giản.

Ví dụ:

Route::redirect('/here', '/there');

Mặc định, Route::redirect sẽ trả về mã trạng thái 302. Mã trạng thái 302 cho biết rằng tài nguyên đã được di chuyển tạm thời đến một vị trí mới.

Tuỳ Chỉnh Mã Trạng Thái

Bạn có thể tuỳ chỉnh mã trạng thái bằng cách sử dụng tham số thứ ba tùy chọn:

Route::redirect('/here', '/there', 301);

Trong ví dụ này, mã trạng thái 301 được sử dụng để chỉ ra rằng tài nguyên đã được di chuyển vĩnh viễn đến một vị trí mới.

Sử Dụng Route::permanentRedirect

Hoặc, bạn có thể sử dụng phương thức Route::permanentRedirect để trả về mã trạng thái 301:

Route::permanentRedirect('/here', '/there');

9. The Route List

Lệnh Artisan route:list là một công cụ mạnh mẽ giúp bạn dễ dàng xem tất cả các route đã được định nghĩa trong ứng dụng của bạn. Dưới đây là các cách sử dụng lệnh route:list cùng với giải thích chi tiết:

Hiển Thị Danh Sách Các Route

Để xem tất cả các route được định nghĩa trong ứng dụng của bạn, bạn có thể sử dụng lệnh:

php artisan route:list

Lệnh này hiển thị một bảng tổng quan của tất cả các route trong ứng dụng, bao gồm các thông tin như phương thức HTTP, URI, tên route, và hành động (action) của route đó. Đây là cách nhanh chóng để bạn kiểm tra cấu hình các route hiện tại của ứng dụng.

Hiển Thị Middleware và Tên Các Nhóm Middleware

Mặc định, lệnh route:list không hiển thị các middleware gán cho mỗi route. Để hiển thị các middleware và tên các nhóm middleware, bạn có thể sử dụng tùy chọn -v:

php artisan route:list -v

Thêm -v (verbose) vào lệnh sẽ hiển thị thêm các thông tin về các middleware áp dụng cho từng route. Nếu bạn muốn mở rộng thêm thông tin về các nhóm middleware, bạn có thể sử dụng -vv:

php artisan route:list -vv

Tùy chọn -vv cung cấp một cái nhìn chi tiết hơn về các nhóm middleware và các middleware cá nhân được gán cho các route, giúp bạn thấy rõ hơn cách các route được xử lý.

Hiển Thị Các Route Bắt Đầu Với Một URI Cụ Thể

Để chỉ hiển thị các route bắt đầu với một URI cụ thể, bạn có thể sử dụng tùy chọn --path:

php artisan route:list --path=api

Thêm tùy chọn --path=api sẽ lọc các route và chỉ hiển thị các route có URI bắt đầu bằng /api. Đây là cách hữu ích để bạn chỉ xem các route liên quan đến API của bạn.

Ẩn Các Route Được Định Nghĩa Bởi Các Gói Thứ Ba

Để ẩn bất kỳ route nào được định nghĩa bởi các gói bên ngoài, bạn có thể sử dụng tùy chọn --except-vendor:

php artisan route:list --except-vendor

Tùy chọn --except-vendor sẽ loại bỏ các route đến từ các gói bên ngoài, giúp bạn tập trung vào các route được định nghĩa trong ứng dụng của bạn.

Chỉ Hiển Thị Các Route Được Định Nghĩa Bởi Các Gói Thứ Ba

Ngược lại, để chỉ hiển thị các route được định nghĩa bởi các gói bên ngoài, bạn có thể sử dụng tùy chọn --only-vendor:

php artisan route:list --only-vendor

Tùy chọn --only-vendor sẽ lọc các route và chỉ hiển thị các route đến từ các gói bên ngoài, giúp bạn xem xét các route của bên thứ ba mà không bị phân tâm bởi các route của ứng dụng của bạn.

Tóm Tắt Các Tùy Chọn Của route:list

  • php artisan route:list: Hiển thị danh sách tất cả các route.
  • php artisan route:list -v: Hiển thị danh sách route kèm theo thông tin về middleware và nhóm middleware.
  • php artisan route:list -vv: Hiển thị thông tin chi tiết về middleware và nhóm middleware.
  • php artisan route:list --path=api: Hiển thị các route có URI bắt đầu bằng /api.
  • php artisan route:list --except-vendor: Ẩn các route từ các gói bên ngoài.
  • php artisan route:list --only-vendor: Chỉ hiển thị các route từ các gói bên ngoài.

Tóm lại

Route là một phần không thể thiếu trong bất kỳ ứng dụng Laravel nào. Việc hiểu rõ và sử dụng thành thạo các route cơ bản sẽ giúp bạn xây dựng ứng dụng một cách hiệu quả và dễ dàng. Hy vọng bài viết này đã giúp bạn có cái nhìn tổng quan về hệ thống routing trong Laravel.

# Optional Parameters

Khi làm việc với các route trong Laravel, đôi khi bạn cần định nghĩa một tham số route mà không phải lúc nào cũng có mặt trong URI. Bạn có thể thực hiện điều này bằng cách đặt dấu ? sau tên tham số và cung cấp một giá trị mặc định cho biến tương ứng trong route. Dưới đây là cách làm việc với tham số route tùy chọn, cùng với các ví dụ và giải thích chi tiết.

Route::get('/user/{name?}', function (?string $name = null) {
    return $name;
});
 
Route::get('/user/{name?}', function (?string $name = 'John') {
    return $name;
});

1. Ràng Buộc Định Dạng Tham Số Route

Dưới đây là tổng hợp các cách sử dụng ràng buộc biểu thức chính quy cho tham số route trong Laravel:

// Ràng buộc tham số phải chỉ chứa các ký tự chữ cái
Route::get('/user/{name}', function (string $name) {
    // ...
})->where('name', '[A-Za-z]+');

// Ràng buộc tham số phải chỉ chứa các chữ số
Route::get('/user/{id}', function (string $id) {
    // ...
})->where('id', '[0-9]+');

// Ràng buộc nhiều tham số với các biểu thức chính quy khác nhau
Route::get('/user/{id}/{name}', function (string $id, string $name) {
    // ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

// Sử dụng các phương thức tiện ích để thêm ràng buộc
Route::get('/user/{id}/{name}', function (string $id, string $name) {
    // ...
})->whereNumber('id')->whereAlpha('name');

Route::get('/user/{name}', function (string $name) {
    // ...
})->whereAlphaNumeric('name');

Route::get('/user/{id}', function (string $id) {
    // ...
})->whereUuid('id');

Route::get('/user/{id}', function (string $id) {
    //
})->whereUlid('id');

Route::get('/category/{category}', function (string $category) {
    // ...
})->whereIn('category', ['movie', 'song', 'painting']);

// Ràng buộc toàn cục cho tham số route
public function boot(): void
{
    Route::pattern('id', '[0-9]+');
}

// Cho phép ký tự '/' trong giá trị tham số
Route::get('/search/{search}', function (string $search) {
    return $search;
})->where('search', '.*');

# Route Naming

Trong Laravel, bạn có thể đặt tên cho các route để tiện lợi hơn trong việc tạo URL hoặc chuyển hướng. Điều này giúp quản lý và tham chiếu đến các route dễ dàng hơn. Dưới đây là cách sử dụng route được đặt tên và các ví dụ cụ thể.

1. Đặt Tên Cho Route

Bạn có thể đặt tên cho một route bằng cách sử dụng phương thức name sau khi định nghĩa route.

Ví Dụ

Route::get('/user/profile', function () {
    // ...
})->name('profile');

Giải Thích

  • ->name('profile'): Đặt tên profile cho route /user/profile.

2. Đặt Tên Cho Route Trong Controller

Bạn cũng có thể đặt tên cho các route trỏ tới các action trong controller:

Ví Dụ

Route::get('/user/profile', [UserProfileController::class, 'show'])->name('profile');

Giải Thích

  • [UserProfileController::class, 'show']: Định nghĩa route trỏ tới phương thức show trong controller UserProfileController.
  • ->name('profile'): Đặt tên profile cho route này.

3. Tạo URL Từ Route Được Đặt Tên

Sau khi đã đặt tên cho một route, bạn có thể sử dụng tên của route để tạo URL hoặc chuyển hướng bằng các hàm trợ giúp của Laravel như routeredirect.

Tạo URL

$url = route('profile');
// Chuyển hướng
return redirect()->route('profile');
 
return to_route('profile');

Giải Thích

  • route('profile'): Tạo URL tới route có tên profile.
  • redirect()->route('profile'): Chuyển hướng tới route có tên profile.
  • to_route('profile'): Một cách khác để chuyển hướng tới route có tên profile.

4. Truyền Tham Số Cho Route Được Đặt Tên

Nếu route có các tham số, bạn có thể truyền các tham số này như một mảng đối số thứ hai cho hàm route.

Ví Dụ

Route::get('/user/{id}/profile', function (string $id) {
    // ...
})->name('profile');
 
$url = route('profile', ['id' => 1]);

Giải Thích

  • ['id' => 1]: Tham số id được truyền vào URL.

5. Thêm Tham Số Vào Query String

Nếu bạn truyền thêm các tham số vào mảng, các cặp key/value này sẽ tự động được thêm vào query string của URL.

Ví Dụ

Route::get('/user/{id}/profile', function (string $id) {
    // ...
})->name('profile');
 
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
 
// Kết quả: /user/1/profile?photos=yes

Giải Thích

  • ['id' => 1, 'photos' => 'yes']: Tham số photos được thêm vào query string của URL.

6. Thiết Lập Giá Trị Mặc Định Cho Tham Số URL

Bạn có thể thiết lập các giá trị mặc định cho tham số URL sử dụng phương thức URL::defaults.

7. Kiểm Tra Route Hiện Tại

Bạn có thể kiểm tra xem request hiện tại có được định tuyến tới một route cụ thể hay không bằng phương thức named trên một instance của Route. Điều này hữu ích khi làm việc với middleware.

Ví Dụ Trong Middleware

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
public function handle(Request $request, Closure $next): Response
{
    if ($request->route()->named('profile')) {
        // ...
    }
 
    return $next($request);
}

Giải Thích

  • $request->route()->named('profile'): Kiểm tra nếu route hiện tại có tên profile.

# Route Caching

Khi triển khai ứng dụng Laravel lên môi trường sản xuất, bạn nên tận dụng khả năng cache route của Laravel để tăng tốc độ xử lý. Việc sử dụng cache route sẽ giảm đáng kể thời gian cần thiết để đăng ký tất cả các route của ứng dụng. Dưới đây là cách tạo và quản lý cache route trong Laravel.

1. Tạo Route Cache

Để tạo cache cho các route, bạn sử dụng lệnh Artisan route:cache:

php artisan route:cache

Giải Thích

  • Lệnh php artisan route:cache: Tạo một file cache chứa tất cả các route của ứng dụng. Sau khi lệnh này được thực thi, file cache sẽ được tải lên mỗi khi có yêu cầu đến ứng dụng, giúp tăng tốc độ xử lý route.

2. Lưu Ý Khi Sử Dụng Route Cache

Sau khi chạy lệnh route:cache, file cache sẽ được tải mỗi khi có yêu cầu đến ứng dụng. Tuy nhiên, nếu bạn thêm hoặc thay đổi bất kỳ route nào, bạn cần tạo lại cache mới. Do đó, bạn chỉ nên chạy lệnh route:cache trong quá trình triển khai (deployment) của dự án.

3. Xóa Route Cache

Nếu bạn cần xóa cache route, bạn có thể sử dụng lệnh Artisan route:clear:

php artisan route:clear

Giải Thích

  • Lệnh php artisan route:clear: Xóa bỏ file cache route hiện tại. Điều này hữu ích khi bạn muốn cập nhật route mà không cần tạo cache mới ngay lập tức.

Quy Trình Sử Dụng Route Cache Trong Deployment

  1. Triển khai ứng dụng lên môi trường sản xuất.
  2. Chạy lệnh php artisan route:cache để tạo file cache cho route.
  3. Khi cần cập nhật hoặc thêm route mới, hãy chạy lệnh php artisan route:clear để xóa cache hiện tại và sau đó tạo lại cache bằng lệnh php artisan route:cache.

Ví Dụ Quy Trình Deployment

# Bước 1: Triển khai ứng dụng
# (Thực hiện các bước triển khai thông thường như kéo code mới, cài đặt dependency, v.v.)

# Bước 2: Tạo route cache
php artisan route:cache

# Sau khi thêm hoặc thay đổi route
# Bước 3: Xóa route cache hiện tại
php artisan route:clear

# Bước 4: Tạo lại route cache mới
php artisan route:cache

Tóm Tắt

Việc sử dụng cache route trong Laravel giúp cải thiện hiệu suất của ứng dụng khi triển khai lên môi trường sản xuất. Tuy nhiên, bạn cần nhớ rằng mỗi khi thay đổi hoặc thêm mới route, bạn phải xóa cache cũ và tạo lại cache mới. Điều này đảm bảo rằng ứng dụng của bạn luôn sử dụng các route mới nhất mà bạn đã định nghĩa.

# Tạo cache cho route
php artisan route:cache

# Xóa cache route hiện tại
php artisan route:clear

Bằng cách tuân thủ quy trình trên, bạn sẽ có thể tận dụng tối đa hiệu quả của tính năng route cache trong Laravel, giúp ứng dụng của bạn hoạt động nhanh hơn và hiệu quả hơn.

 

Blade Basics

Blade Basics

01.08.2024
Author: ADMIN

# Blade Basics

Blade là một công cụ tạo template (template engine) mạnh mẽ được tích hợp sẵn trong Laravel. Nó cho phép bạn sử dụng các cấu trúc điều khiển như if, for, while,... ngay trong các file template của bạn. Dưới đây là một số khái niệm cơ bản và ví dụ minh họa để bạn có thể bắt đầu sử dụng Blade.

1. Tạo Và Sử Dụng File Blade

Các file Blade có đuôi mở rộng là .blade.php. Ví dụ, bạn có thể tạo một file Blade cho trang chủ của ứng dụng như sau:

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home Page</title>
</head>
<body>
    <h1>Welcome to My Laravel Application</h1>
</body>
</html>

Để trả về view này từ một route, bạn có thể sử dụng phương thức view của Laravel:

Route::get('/', function () {
    return view('home');
});

2. Các Cấu Trúc Điều Khiển

If Statements

Blade hỗ trợ các cấu trúc điều khiển như if, elseif, else, và endif:

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

@if ($name == 'John')
    <p>Hello, John!</p>
@elseif ($name == 'Jane')
    <p>Hello, Jane!</p>
@else
    <p>Hello, Stranger!</p>
@endif

Loops

Blade cũng hỗ trợ các cấu trúc lặp như for, foreach, forelse, và while:

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

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

3. Echoing Data

Blade cung cấp cú pháp đơn giản để hiển thị dữ liệu từ các biến PHP:

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

<p>{{ $name }}</p>
<p>{{ $age }}</p>

Bạn cũng có thể sử dụng hàm @php để nhúng mã PHP trực tiếp vào file Blade:

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

@php
    $name = 'John';
@endphp

<p>{{ $name }}</p>

4. Escape HTML

Blade sẽ tự động escape các biến để bảo vệ ứng dụng của bạn khỏi các lỗ hổng XSS. Nếu bạn muốn hiển thị dữ liệu mà không escape, bạn có thể sử dụng cú pháp sau:

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

{!! $unescapedData !!}

5. Kế Thừa Layouts

Blade cung cấp cơ chế kế thừa layout giúp bạn tạo ra các template có cấu trúc lặp lại một cách dễ dàng.

Tạo Layout

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
</body>
</html>

Sử Dụng Layout

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

@extends('layouts.app')

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

@section('content')
    <h1>Welcome to My Laravel Application</h1>
@endsection

6. Bao Gồm Các View Con (Including Sub-Views)

Bạn có thể chia nhỏ view thành các phần nhỏ hơn và bao gồm chúng vào view chính:

<!-- resources/views/includes/header.blade.php -->

<header>
    <h1>Header Content</h1>
</header>

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

@include('includes.header')