9 Tips about Blade

9 Tips about Blade

01.08.2024
Author: ADMIN

# 9 Tips about Blade

1. Sử dụng forelse thay vì foreach

Trong Laravel Blade, forelse là một cấu trúc vòng lặp hữu ích khi bạn muốn xử lý trường hợp một mảng là rỗng. Nó giúp bạn  lặp qua một mảng và cung cấp một cấu trúc điều kiện để hiển thị nội dung khi mảng rỗng.

ví dụ:

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

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

@if ($users->isEmpty())
    <p>No users found.</p>
@endif

// Replace

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

@forelse ($users as $user)
    <p>This is user {{ $user->name }}</p>
@empty
    <p>No users found.</p>
@endforelse

Giải Thích

  • @forelse ($users as $user): Nếu mảng $users không rỗng, vòng lặp này sẽ lặp qua từng phần tử trong mảng.
  • @empty: Nếu mảng $users rỗng, đoạn mã trong khối @empty sẽ được thực thi.
  • @endforelse: Kết thúc vòng lặp forelse.

2. Sử dụng @auth@guest

Laravel cung cấp các directive @auth@guest trong Blade để giúp bạn kiểm tra trạng thái xác thực của người dùng một cách dễ dàng. Đây là hai directive rất hữu ích khi bạn cần hiển thị nội dung khác nhau dựa trên việc người dùng đã đăng nhập hay chưa.

2.1. Directive @auth

Directive @auth được sử dụng để kiểm tra xem người dùng hiện tại có được xác thực hay không. Nếu người dùng đã đăng nhập, nội dung bên trong directive này sẽ được hiển thị.

Cú Pháp

@auth
    <!-- Nội dung dành cho người dùng đã đăng nhập -->
@endauth

Ví Dụ

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome Page</title>
</head>
<body>
    <h1>Welcome to My Laravel Application</h1>
    
    @auth
        <p>Welcome back, {{ Auth::user()->name }}!</p>
        <a href="{{ route('logout') }}">Logout</a>
    @endauth
</body>
</html>

2.2. Directive @guest

Directive @guest được sử dụng để kiểm tra xem người dùng hiện tại có chưa được xác thực hay không. Nếu người dùng chưa đăng nhập, nội dung bên trong directive này sẽ được hiển thị.

Cú Pháp

@guest
    <!-- Nội dung dành cho người dùng chưa đăng nhập -->
@endguest

Ví Dụ

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome Page</title>
</head>
<body>
    <h1>Welcome to My Laravel Application</h1>
    
    @guest
        <p>Please <a href="{{ route('login') }}">login</a> to access more features.</p>
        <a href="{{ route('register') }}">Register</a>
    @endguest
</body>
</html>

3. Sử dụng auth()->user()

Trong các file Blade, bạn có thể sử dụng auth()->user() để hiển thị thông tin người dùng hiện tại.

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Profile Page</title>
</head>
<body>
    <h1>Profile</h1>
    
    @if(auth()->check())
        <p>Name: {{ auth()->user()->name }}</p>
        <p>Email: {{ auth()->user()->email }}</p>
    @else
        <p>Please <a href="{{ route('login') }}">login</a> to view your profile.</p>
    @endif
</body>
</html>

Các Phương Thức Hữu Ích Khác

  • auth()->check(): Kiểm tra xem có người dùng nào đã đăng nhập hay không.
  • auth()->id(): Lấy ID của người dùng đã đăng nhập.

4. Format Carbon Dates

Carbon cung cấp nhiều phương thức để định dạng ngày và giờ, bao gồm toFormattedDateString, diffForHumans, và nhiều hơn nữa.

<p>Created at: {{ $post->created_at->toFormattedDateString() }}</p>
<p>Created at: {{ $post->created_at->diffForHumans() }}</p>
<p>Created at: {{ $post->created_at->format('l, d F Y H:i') }}</p>

Bạn có thể tạo một custom Blade directive để định dạng ngày và giờ một cách nhất quán.

Tạo Custom Blade Directive

Trong AppServiceProvider, bạn có thể đăng ký một custom Blade directive.

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Carbon\Carbon;

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

    public function register()
    {
        //
    }
}

Sử Dụng Custom Blade Directive

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Show Date</title>
</head>
<body>
    <h1>Show Date</h1>
    
    <p>Created at: @datetime($post->created_at)</p>
</body>
</html>

5. Route::view()

Trong Laravel, phương thức Route::view cung cấp một cách tiện lợi để định nghĩa các tuyến đường (route) mà không cần một controller. Nó rất hữu ích cho các trang tĩnh hoặc các trang có ít logic.

Cú Pháp Route::view

Cú pháp cơ bản của Route::view như sau:

Route::view($uri, $view, $data = []);
  • $uri: URL của tuyến đường.
  • $view: Tên của view sẽ được trả về.
  • $data: (Tùy chọn) Mảng dữ liệu sẽ được truyền tới view.

Ví Dụ

Dưới đây là một số ví dụ về cách sử dụng Route::view trong tệp routes/web.php.

1. Định Nghĩa Một Tuyến Đường Đơn Giản

Giả sử bạn có một view tĩnh tên là welcome.blade.php trong thư mục resources/views.

Route::view('/welcome', 'welcome');

Khi người dùng truy cập vào URL /welcome, họ sẽ thấy nội dung của view welcome.blade.php.

2. Truyền Dữ Liệu Tới View

Bạn cũng có thể truyền dữ liệu tới view bằng cách sử dụng tham số thứ ba của Route::view.

Route::view('/about', 'about', ['name' => 'Laravel']);

Trong view about.blade.php, bạn có thể truy cập dữ liệu này như sau:

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>About</title>
</head>
<body>
    <h1>About</h1>
    <p>This application is built with {{ $name }}.</p>
</body>
</html>

6. Blade Error Pages

Laravel cung cấp các trang lỗi mặc định cho các mã lỗi HTTP khác nhau, chẳng hạn như 404 (Not Found), 500 (Internal Server Error), v.v. Tuy nhiên, bạn có thể tùy chỉnh các trang lỗi này để phù hợp với giao diện và trải nghiệm người dùng của ứng dụng của mình.

Để tùy chỉnh các trang lỗi, Laravel cung cấp một cách dễ dàng để xuất bản các file view lỗi mặc định vào thư mục views của bạn bằng lệnh php artisan vendor:publish.

Bước 1: Xuất Bản Các Trang Lỗi

Bạn có thể sử dụng lệnh php artisan vendor:publish --tag=laravel-errors để xuất bản các trang lỗi mặc định vào thư mục resources/views/errors của dự án của bạn.

Lệnh

php artisan vendor:publish --tag=laravel-errors

Lệnh này sẽ tạo các file view lỗi trong thư mục resources/views/errors của dự án của bạn.

Bước 2: Tùy Chỉnh Các Trang Lỗi

Sau khi các file view lỗi đã được xuất bản, bạn có thể tùy chỉnh chúng theo ý muốn của mình. Mỗi file đại diện cho một mã lỗi HTTP cụ thể. Ví dụ, bạn sẽ có các file như 404.blade.php, 500.blade.php, v.v.

Ví Dụ Tùy Chỉnh Trang 404

<!-- resources/views/errors/404.blade.php -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Page Not Found</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            padding: 50px;
        }
        h1 {
            font-size: 50px;
        }
        p {
            font-size: 20px;
        }
        a {
            color: #3490dc;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <h1>404</h1>
    <p>Sorry, the page you are looking for could not be found.</p>
    <p><a href="{{ url('/') }}">Go to Homepage</a></p>
</body>
</html>

Bước 3: Kiểm Tra Các Trang Lỗi

Sau khi tùy chỉnh các trang lỗi, bạn có thể kiểm tra chúng bằng cách truy cập vào các URL không tồn tại hoặc gây ra các lỗi khác nhau trong ứng dụng của bạn. Ví dụ, truy cập một URL không tồn tại để kiểm tra trang 404.

Tóm Tắt

  • Xuất bản các trang lỗi: Sử dụng lệnh php artisan vendor:publish --tag=laravel-errors để xuất bản các file view lỗi mặc định.
  • Tùy chỉnh các trang lỗi: Chỉnh sửa các file trong resources/views/errors để phù hợp với giao diện của ứng dụng của bạn.
  • Kiểm tra các trang lỗi: Truy cập các URL không tồn tại hoặc gây ra các lỗi khác để xem các trang lỗi tùy chỉnh của bạn.

Việc tùy chỉnh các trang lỗi giúp bạn tạo ra một trải nghiệm người dùng nhất quán và chuyên nghiệp hơn, ngay cả khi có lỗi xảy ra trong ứng dụng của bạn.

7. Artisan view:clear

Trong Laravel, lệnh Artisan view:clear được sử dụng để xóa bộ nhớ cache của các file view đã được biên dịch. Đây là một lệnh hữu ích khi bạn thực hiện các thay đổi trong view và muốn chắc chắn rằng ứng dụng của bạn sẽ sử dụng các file view mới nhất mà không bị ảnh hưởng bởi các phiên bản đã được cache.

Cách Sử Dụng view:clear

Lệnh

Bạn có thể chạy lệnh này từ terminal bằng cách sử dụng:

php artisan view:clear

Kết Quả

Lệnh này sẽ xóa tất cả các file view đã được biên dịch và lưu trữ trong thư mục storage/framework/views. Sau khi lệnh được thực thi, Laravel sẽ biên dịch lại các file view khi chúng được yêu cầu lần tiếp theo.

Khi Nào Nên Sử Dụng view:clear

  • Khi Phát Triển: Nếu bạn thấy rằng các thay đổi bạn thực hiện trong view không được áp dụng, bạn có thể chạy lệnh này để xóa bộ nhớ cache và đảm bảo rằng các thay đổi sẽ được nhìn thấy.
  • Khi Triển Khai: Sau khi triển khai ứng dụng lên môi trường production, bạn có thể chạy lệnh này để xóa bộ nhớ cache cũ và buộc Laravel biên dịch lại các view với các thay đổi mới nhất.

8. Asset() helper

Trong Laravel, helper asset() được sử dụng để tạo URL tuyệt đối tới các tài nguyên công cộng (public assets) như hình ảnh, CSS, JavaScript, v.v. Helper này rất hữu ích để đảm bảo rằng các đường dẫn tới tài nguyên của bạn luôn chính xác, bất kể ứng dụng của bạn đang chạy trên môi trường nào.

asset($path, $secure = null)
  • $path: Đường dẫn tới tài nguyên tính từ thư mục public.
  • $secure: Tham số tùy chọn, nếu đặt là true, URL sẽ được tạo với HTTPS. Nếu không, HTTP sẽ được sử dụng.

9. Meta Title

Meta title là một phần quan trọng trong SEO và trải nghiệm người dùng, hiển thị tiêu đề của trang web trên trình duyệt và trong kết quả tìm kiếm. Trong Laravel Blade, bạn có thể dễ dàng thiết lập và tùy chỉnh meta title cho các trang web của mình.

Cách Thiết Lập Meta Title

Để thiết lập meta title trong Laravel Blade, bạn có thể sử dụng thẻ <title> trong phần <head> của HTML.

Sử Dụng @section và @yield

Nếu bạn sử dụng layout trong Laravel Blade, bạn có thể thiết lập meta title bằng cách sử dụng @section@yield.

Layout (layouts/app.blade.php)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    <header>
        <h1>My Website</h1>
    </header>

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

View (home.blade.php)

@extends('layouts.app')

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

@section('content')
    <h2>Welcome to the Home Page</h2>
    <p>This is the home page of the website.</p>
@endsection

Sử Dụng @push và @stack

Một cách khác để thiết lập meta title là sử dụng @push@stack.

Layout (layouts/app.blade.php)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>@stack('title')</title>
</head>
<body>
    <header>
        <h1>My Website</h1>
    </header>

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

View (home.blade.php)

@extends('layouts.app')

@push('title')
    Home Page
@endpush

@section('content')
    <h2>Welcome to the Home Page</h2>
    <p>This is the home page of the website.</p>
@endsection
Ví dụ về các vấn đề truy vấn N+1

Ví dụ về các vấn đề truy vấn N+1

01.08.2024
Author: ADMIN

# Vấn Đề N+1 Query Trong Eloquent

Vấn đề N+1 query là một trong những vấn đề phổ biến mà các nhà phát triển gặp phải khi làm việc với ORM như Eloquent trong Laravel. Vấn đề này xảy ra khi ứng dụng của bạn thực hiện một lượng lớn các truy vấn nhỏ lặp đi lặp lại để lấy dữ liệu liên quan, thay vì chỉ thực hiện một vài truy vấn lớn hơn, dẫn đến giảm hiệu suất ứng dụng. Dưới đây là bốn ví dụ về vấn đề N+1 query và cách giải quyết chúng.

# Laravel Debugbar

Trước khi vào các ví dụ cụ thể, bạn nên cài đặt Laravel Debugbar để có thể kiểm tra  và debug các ứng dụng Laravel một cách dễ dàng. Debugbar hiển thị các thông tin chi tiết về các truy vấn cơ sở dữ liệu, các biến session, các yêu cầu HTTP và nhiều thông tin khác ngay trên giao diện của ứng dụng.

composer require barryvdh/laravel-debugbar --dev

Tiếp theo, bạn chỉ cần kích hoạt chế độ gỡ lỗi với biến APP_DEBUG=true trong file .env

// .env
APP_DEBUG=true 

Ví Dụ 1: Lấy Dữ Liệu Liên Quan Trong Vòng Lặp

Mã Gặp Vấn Đề N+1 Query:
$posts = Post::all();

foreach ($posts as $post) {
    echo $post->user->name;
}
Giải Thích:

Đoạn mã trên sẽ thực hiện một truy vấn để lấy tất cả các bài viết. Sau đó, nó sẽ thực hiện một truy vấn riêng lẻ cho mỗi bài viết để lấy thông tin người dùng liên quan, dẫn đến tổng cộng 1 + N truy vấn (N là số lượng bài viết).

Giải Quyết Sử Dụng Eager Loading:
$posts = Post::with('user')->get();

foreach ($posts as $post) {
    echo $post->user->name;
}
Giải Thích:

Bằng cách sử dụng phương thức with, chúng ta chỉ thực hiện hai truy vấn: một truy vấn để lấy tất cả các bài viết và một truy vấn để lấy tất cả các người dùng liên quan.

Ví Dụ 2: Ký hiệu

Giả sử bạn có cùng mối quan hệ hasMany giữa tác giả và sách và bạn cần liệt kê các tác giả cùng số lượng sách của mỗi tác giả.

// Controller

public function index()
{
    $authors = Author::with('books')->get();
 
    return view('authors.index', compact('authors'));
}

Và sau đó, trong tệp Blade, bạn thực hiện một vòng lặp foreach cho bảng:

@foreach($authors as $author)
    <tr>
        <td>{{ $author->name }}</td>
        <td>{{ $author->books()->count() }}</td>
    </tr>
@endforeach

Mọi thứ trông có vẻ hợp lý, đúng không? Nhưng nhìn vào dữ liệu Debugbar bên dưới.

Chúng ta đang sử dụng eager loading, Author::with('books'), nhưng tại sao lại có nhiều truy vấn xảy ra như thế?

Bởi vì, trong Blade,  $author->books()->count() không load mối quan hệ từ bộ nhớ.

  • $author->books() có nghĩa là PHƯƠNG THỨC của mối quan hệ
  • $author->books có nghĩa là DỮ LIỆU được eager loaded vào bộ nhớ

Vậy, phương pháp liên kết sẽ truy vấn cơ sở dữ liệu cho mỗi tác giả. Nhưng nếu bạn tải dữ liệu mà không có dấu ngoặc "()", nó sẽ thành công sử dụng dữ liệu được eager loading:

Vì vậy, hãy chú ý đến chính xác những gì bạn đang sử dụng - phương pháp quan hệ hay dữ liệu.

Lưu ý rằng trong ví dụ cụ thể này có một giải pháp thậm chí còn tốt hơn. Nếu bạn chỉ cần dữ liệu tổng hợp được tính toán của mối quan hệ, mà không cần mô hình đầy đủ, thì bạn chỉ nên tải các tổng hợp, như withCount:

// Controller:
$authors = Author::withCount('books')->get();
 
// Blade:
{{ $author->books_count }}

Kết quả sẽ chỉ có MỘT truy vấn đến cơ sở dữ liệu, thậm chí không phải là hai truy vấn. Và bộ nhớ cũng sẽ không bị "polluted" với dữ liệu quan hệ, do đó cũng tiết kiệm được một số RAM.

Ví Dụ 3: Mối quan hệ "ẩn" trong Accessor

Hãy lấy một ví dụ tương tự: danh sách các tác giả, với cột cho biết tác giả có hoạt động hay không: "Có" hoặc "Không". Hoạt động đó được xác định bởi việc tác giả có ít nhất một cuốn sách hay không và được tính như một accessor bên trong mô hình Author.

// Controller:
public function index()
{
    $authors = Author::all();
 
    return view('authors.index', compact('authors'));
}

// Blade file
@foreach($authors as $author)
    <tr>
        <td>{{ $author->name }}</td>
        <td>{{ $author->is_active ? 'Yes' : 'No' }}</td>
    </tr>
@endforeach

"is_active" được định nghĩa trong model Eloquent:

use Illuminate\Database\Eloquent\Casts\Attribute;
 
class Author extends Model
{
    public function isActive(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->books->count() > 0,
        );
    }
}

Hãy xem Debugbar hiển thị những gì:

Đúng, chúng ta có thể giải quyết bằng  eager loading các sách trong Controller. Nhưng trong trường hợp này, lời khuyên chung của tôi là tránh sử dụng các mối quan hệ trong accessor . Bởi vì accessor thường được sử dụng khi hiển thị dữ liệu và trong tương lai, người khác có thể sử dụng accessor này trong một số tệp Blade khác và bạn sẽ không kiểm soát được Controller đó trông như thế nào.

Nói cách khác, Accessor được cho là một phương pháp có thể tái sử dụng để định dạng dữ liệu, do đó bạn không kiểm soát được khi nào/cách thức dữ liệu sẽ được tái sử dụng. Trong trường hợp hiện tại của bạn, bạn có thể tránh truy vấn N+1, nhưng trong tương lai, người khác có thể không nghĩ đến nó.

# Giải pháp tích hợp chống lại truy vấn N + 1
Add eloquent strict loading mode

Laravel Routing – 8 Advanced Tips

Laravel Routing – 8 Advanced Tips

01.08.2024
Author: ADMIN

# Laravel Routing – 8 Advanced Tips

Chúng ta tất cả đều sử dụng cú pháp đơn giản của Route::get() và Route::post(), nhưng trong các dự án lớn, nó trở nên phức tạp hơn nhiều. Bài viết này sẽ tổng hợp các mẹo khác nhau cho các tình huống khác nhau.

Tip 1. Route::get() BEFORE Route::resource()

Đối với Resource Controllers, đây là một trong những sai lầm phổ biến nhất, hãy xem ví dụ này:

Route::resource('photos', 'PhotoController');
Route::get('photos/popular', 'PhotoController@method');

Khi bạn định nghĩa một route resource, Laravel tự động tạo ra nhiều route cho các hành động CRUD (Create, Read, Update, Delete)

Điều này sẽ tạo ra các route như /photos, /photos/{id}, /photos/{id}/edit, và nhiều hơn nữa. Nếu bạn có một route thêm vào, ví dụ như /photos/popular, mà bạn định nghĩa sau route resource, thì có thể xảy ra xung đột. Điều này là do Laravel ưu tiên các route định nghĩa trước. Vì vậy, nếu bạn đặt route thêm vào sau route resource, nó có thể không hoạt động như mong muốn. Trong ví dụ này, route /photos/popular có thể bị route resource /photos/{id} chặn và sẽ được gán giá trị "popular" làm tham số {id}.

Vì vậy, cú pháp đúng phải là: 

// Đặt route bổ sung trước
Route::get('photos/popular', 'PhotoController@method');

// Sau đó định nghĩa route resource
Route::resource('photos', 'PhotoController');

Tip 2. Group in Another Group

Chúng ta có lẽ đều biết rằng có thể nhóm các route bằng Route::group() và gán các middleware/prefixes khác nhau cùng các tham số khác, như các route công khai và các route yêu cầu đăng nhập.

Nhưng nếu bạn cần một tập hợp các quy tắc nhất định cho các nhóm con của những nhóm đó thì sao?

Ví dụ điển hình: bạn cần các route công khai và các route yêu cầu đăng nhập, nhưng trong nhóm các route yêu cầu đăng nhập, bạn cần tách biệt quản trị viên khỏi người dùng thông thường.

Vì vậy, bạn có thể làm điều này:

// route công khai
Route::get('/', 'HomeController@index');

// Người dùng đã đăng nhập - với middleware "auth"
Route::group(['middleware' => ['auth']], function () {

    // /user/XXX: Bên cạnh "auth", nhóm này sẽ có middleware "simple_users"
    Route::group(['middleware' => ['simple_users'], 'prefix' => 'user'], function () {
        Route::resource('tasks', 'TaskController');
    });

    // /admin/XXX: Nhóm này sẽ không có "simple_users", nhưng sẽ có "auth" và "admins"
    Route::group(['middleware' => ['admins'], 'prefix' => 'admin'], function () {
        Route::resource('users', 'UserController');
    });
});

Tip 3. Route Parameter Validation – Multi-Language Example

Một trường hợp khá điển hình là sử dụng prefix cho các route của bạn theo ngôn ngữ địa phương, ví dụ như fr/blogen/article/333. Làm thế nào để chúng ta đảm bảo rằng hai chữ cái đầu tiên đó không được sử dụng cho mục đích khác ngoài ngôn ngữ?

Chúng ta có thể xác thực trực tiếp trong route bằng tham số "where":

Route::group(['prefix' => '{locale}', 'where' => ['locale' => '[a-zA-Z]{2}']], function () {
    Route::get('/', 'HomeController@index');
    Route::get('article/{id}', 'ArticleController@show');
});

Tip 4. Routing với Subdomain Động

Đây là một tính năng đến trực tiếp từ tài liệu chính thức của Laravel, nhưng ít được sử dụng nên mình muốn đề cập đến nó.

Nếu bạn có một subdomain động, như một subdomain khác nhau cho mỗi người dùng, nó cần trở thành một biến, đúng không? Laravel đã tự động làm điều đó cho bạn. Xem ví dụ:

Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        // Code xử lý
    });
});

Giải thích

  • Route::domain('{account}.myapp.com'): Định nghĩa một nhóm các route với một subdomain động {account}. Subdomain này sẽ được thay thế bằng giá trị cụ thể của từng người dùng.

  • group(function () { ... }): Định nghĩa một nhóm các route sẽ thuộc subdomain đã định nghĩa ở trên.

  • Route::get('user/{id}', function ($account, $id) { ... }): Định nghĩa một route trong nhóm này. Route này chấp nhận hai tham số: $account (giá trị của subdomain động) và $id (ID của người dùng).

Lưu ý:

  • {account} tự động được truyền như một tham số $account vào tất cả các phương thức controller bên trong nhóm route này. Vì vậy, bạn cần chấp nhận tham số này trong tất cả các phương thức controller, không quên điều này.

Ví dụ:

  • Subdomain: john.myapp.com
    • Route: john.myapp.com/user/123
    • Controller Method: function ($account, $id)
    • $account sẽ là john$id sẽ là 123.

Tip 5. Cẩn Thận với Route Model Binding Không Dùng Tiếng Anh

Đôi khi, URL cần chứa các từ không phải tiếng Anh. Ví dụ, bạn có một trang web tiếng Tây Ban Nha về sách và bạn muốn có URL như /libros cho danh sách sách, và sách cụ thể sẽ có URL như /libros/1, giống như một Resource Controller thông thường.

Nhưng trong cơ sở dữ liệu, tất cả các tên nên là tiếng Anh để "magic" của Laravel có thể hoạt động giữa dạng số ít và số nhiều, đúng không?

Vì vậy, nếu bạn tạo một model Book với migration và Controller, bạn có thể dùng lệnh sau:

php artisan make:model Book -mcr

Phím -mcr sẽ tạo một model và một resource controller. Trong Controller đó, bạn sẽ có như sau:

/**
 * Display the specified resource.
 *
 * @param  \App\Book  $book
 * @return \Illuminate\Http\Response
 */
public function show(Book $book)
{
    // ...
}

Nhưng trong routes/web.php, bạn sẽ có như sau:

Route::resource('libros', 'BookController');

Vấn đề là nó sẽ không hoạt động. Một vấn đề lớn hơn là nó sẽ không đưa ra bất kỳ lỗi nào, chỉ là biến $book sẽ rỗng, và bạn sẽ không hiểu tại sao.

Theo mô tả của Resource Controller chính thức, tên của biến phải giống với tham số ở dạng số ít:

// Thay vì
public function show(Book $book)
{
    // ...
}

// Bạn nên để
public function show(Book $libro)
{
    // ...
}

Nhưng, thành thật mà nói, trong các dự án không sử dụng tiếng Anh, tôi khuyên không nên sử dụng Route::resource và Route Model Binding. Quá nhiều "magic" không thể đoán trước, như cách Laravel sẽ "đoán" rằng dạng số ít của "libros" là "libro"?

Tip 6. API Routes – từ V1 đến V2

Hãy tưởng tượng bạn đang làm việc với dự án dựa trên API và cần phát hành phiên bản mới của API. Các endpoint cũ sẽ giữ nguyên tại api/[something], và đối với phiên bản mới, bạn sẽ sử dụng api/V2/[something].

Toàn bộ logic nằm trong app/Providers/RouteServiceProvider.php:

public function map()
{
    $this->mapApiRoutes();

    $this->mapWebRoutes();

    // ...
}

protected function mapWebRoutes()
{
    Route::middleware('web')
        ->namespace($this->namespace)
        ->group(base_path('routes/web.php'));
}

protected function mapApiRoutes()
{
    Route::prefix('api')
        ->middleware('api')
        ->namespace($this->namespace)
        ->group(base_path('routes/api.php'));
}

Như bạn có thể thấy, các route API được đăng ký trong một hàm riêng với tiền tố api/.

Vì vậy, nếu bạn muốn tạo nhóm route V2, bạn có thể tạo một tệp riêng routes/api_v2.php và làm như sau:

public function map()
{
    // ... các hàm cũ

    $this->mapApiV2Routes();
}

// Và hàm mới
protected function mapApiV2Routes()
{
    Route::prefix('api/V2')
        ->middleware('api')
        ->namespace($this->namespace)
        ->group(base_path('routes/api_v2.php'));
}

Bằng cách này, các route cũ sẽ không bị phá vỡ, và bạn chỉ cần tạo một bộ route mới.

Tip 7. Giới Hạn Tốc Độ (Rate Limiting) – Tổng Thể và cho Khách/Người Dùng

Điều này cũng xuất phát từ tài liệu chính thức, nhưng với những chi tiết ít được biết đến hơn.

Giới Hạn Tốc Độ Tổng Thể

Đầu tiên, bạn có thể giới hạn một URL được gọi tối đa 60 lần mỗi phút, với throttle:60,1.

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Giới Hạn Tốc Độ Riêng cho Khách và Người Dùng Đã Đăng Nhập

Nhưng bạn có biết rằng bạn có thể làm điều này riêng biệt cho người dùng công khai và người dùng đã đăng nhập không?

// tối đa 10 yêu cầu mỗi phút cho khách và 60 cho người dùng đã đăng nhập
Route::middleware('throttle:10|60,1')->group(function () {
    //
});

Giới Hạn Tốc Độ cho Người Dùng Cụ Thể
Bạn cũng có thể có một trường cơ sở dữ liệu users.rate_limit và giới hạn số lượng yêu cầu cho người dùng cụ thể:

Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Tip 8. Route List and Route Caching

Xem Danh Sách Routes

Không phải tất cả chúng ta đều biết chính xác những routes nào ẩn dưới Route::resource(), hoặc dưới một số câu lệnh Route::group phức tạp hơn. Nhưng vào bất kỳ thời điểm nào, bạn có thể kiểm tra routes thực tế của mình bằng lệnh Artisan:

php artisan route:list

Lệnh này sẽ hiển thị một danh sách tất cả các routes hiện có trong ứng dụng của bạn, bao gồm tên route, phương thức HTTP, URL, tên controller và action tương ứng. Đây là một công cụ rất hữu ích để kiểm tra và gỡ lỗi cấu hình routes của bạn.

Sử Dụng Bộ Nhớ Đệm Routes

Bộ nhớ đệm routes (route caching) là một tính năng mạnh mẽ giúp cải thiện hiệu suất của ứng dụng bằng cách lưu trữ cấu hình routes trong bộ nhớ đệm. Tuy nhiên, khi bạn sử dụng bộ nhớ đệm routes, bạn cần nhớ xóa và tạo lại bộ nhớ đệm sau mỗi lần thay đổi cấu hình routes.

Để xóa bộ nhớ đệm routes:

php artisan route:clear

Sau đó, để tạo lại bộ nhớ đệm routes:

php artisan route:cache

Lệnh này sẽ lưu trữ cấu hình routes của bạn trong bộ nhớ đệm, giúp Laravel tải routes nhanh hơn trong các yêu cầu tiếp theo.

Một số lệnh Artisan Make với các tham số

Một số lệnh Artisan Make với các tham số

01.08.2024
Author: ADMIN

Laravel cung cấp nhiều lệnh Artisan để tạo các thành phần khác nhau trong ứng dụng. Dưới đây là danh sách các lệnh make cùng với các tham số phổ biến mà bạn có thể sử dụng.

1. Make Controller

php artisan make:controller {name} [--resource] [--api] [--invokable] [--model[=MODEL]] [--parent] [--requests] [--singleton] [--force]
  • --resource: Controller sẽ chứa một phương thức cho mỗi hoạt động tài nguyên có sẵn - index(), create(), store(), show(), edit(), update(), destroy().
  • --api: Tương tự như -resource ở trên, nhưng chỉ tạo ra 5 phương thức: index(), store(), show(), update(), destroy(). Bởi vì các biểu mẫu tạo/sửa không cần thiết cho API.
  • --invokable: Tạo một controller với một phương thức __invoke duy nhất.
  • --model[=MODEL]: Tạo controller với mô hình được liên kết.
  • --requests: Tạo các lớp request form cho controller.

2. Make Model

php artisan make:model {name} [--migration] [--controller] [--resource] [--factory] [--seed] [--policy] [--all] [--pivot]
  • --migration: Tạo migration cho mô hình.
  • --controller: Tạo controller cho mô hình.
  • --resource: Tạo controller tài nguyên cho mô hình.
  • --factory: Tạo factory cho mô hình.
  • --seed: Tạo seeder cho mô hình.
  • --policy: Tạo policy cho mô hình.
  • --all: Tạo migration, factory, seeder, policy, và controller cho mô hình.
  • --pivot: Tạo mô hình pivot.

3. Make Migration

php artisan make:migration {name} [--create[=TABLE]] [--table[=TABLE]] [--path[=PATH]] [--realpath] [--fullpath]
  • --create[=TABLE]: Tạo migration cho bảng mới.
  • --table[=TABLE]: Tạo migration để cập nhật bảng hiện có.

4. Make Seeder

php artisan make:seeder {name}

5. Make Factory

php artisan make:factory {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết factory với mô hình.

6. Make Middleware

php artisan make:middleware {name}

7. Make Request

php artisan make:request {name}

8. Make Event

php artisan make:event {name}

9. Make Listener

php artisan make:listener {name} [--event[=EVENT]]
  • --event[=EVENT]: Liên kết listener với sự kiện.

10. Make Job

php artisan make:job {name} [--sync]
  • --sync: Tạo job đồng bộ.

11. Make Notification

php artisan make:notification {name}

12. Make Mail

php artisan make:mail {name} [--markdown[=MARKDOWN]]
  • --markdown[=MARKDOWN]: Tạo email với template markdown.

13. Make Command

php artisan make:command {name} [--command[=COMMAND]]
  • --command[=COMMAND]: Tên của lệnh console.

14. Make Policy

php artisan make:policy {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết policy với mô hình.

15. Make Provider

php artisan make:provider {name}

16. Make Test

php artisan make:test {name} [--unit] [--pest]
  • --unit: Tạo test đơn vị.
  • --pest: Tạo test Pest.

17. Make Rule

php artisan make:rule {name}

18. Make Observer

php artisan make:observer {name} [--model[=MODEL]]
  • --model[=MODEL]: Liên kết observer với mô hình.

19. Make Channel

php artisan make:channel {name}

20. Make Resource

php artisan make:resource {name}

Trên đây là một số command mà tôi hay sử dụng, ngoài các command này, bạn có thể sử dụng command php artisan list để liệt kê tất cả command artisan tính đến thời điểm hiện tại