
Tóm tắt nhanh
- PHP Attributes thay thế protected properties trong Laravel 13
- Hỗ trợ Models, Jobs, Commands, Controllers, và nhiều hơn nữa
- Hoàn toàn backward compatible – không cần viết lại code cũ
- Chiến lược migration: từng bước nhỏ, không refactor một lúc
- Có thể mix giữa properties và attributes trong cùng một file
Cài đặt yêu cầu trước khi migration
Để sử dụng PHP Attributes trong Laravel 13, bạn cần PHP 8.3 trở lên và Laravel 13. Đây là yêu cầu bắt buộc – nếu server của bạn vẫn đang chạy PHP 8.2, hãy nâng cấp lên PHP 8.3 trước.
Để kiểm tra phiên bản PHP hiện tại, bạn chạy:
php -v
Nếu bạn chưa nâng cấp lên Laravel 13, hãy xem bài viết Laravel 13 có gì mới để biết thêm chi tiết về quá trình nâng cấp.
Model Attributes – Eloquent Models
PHP Attributes trong Eloquent Models cho phép bạn khai báo cấu hình model trực tiếp trên class thay vì dùng protected properties. Đây là thay đổi lớn nhất và mang lại visual improvement rõ rệt nhất.
Cách chuyển đổi Model
Trước đây với Laravel 12 trở xuống, bạn viết:
class User extends Model
{
protected $table = 'system_users';
protected $primaryKey = 'user_id';
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = ['name', 'email'];
protected $hidden = ['password', 'remember_token'];
}Với Laravel 13, bạn có thể viết gọn gàng hơn:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Attributes\Table;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
#[Table('system_users', key: 'user_id', keyType: 'string', incrementing: false)]
#[Fillable(['name', 'email'])]
#[Hidden(['password', 'remember_token'])]
class User extends Model
{
// Class body trống - không còn boilerplate!
}Danh sách đầy đủ Model Attributes
- #[Table(‘table_name’)] — thay thế protected $table
- #[PrimaryKey(‘column’)] — thay thế protected $primaryKey
- #[KeyType(‘string’)] — thay thế protected $keyType
- #[Fillable([‘columns’])] — thay thế protected $fillable
- #[Guarded([‘columns’])] — thay thế protected $guarded
- #[Unguarded] — mới, không có property tương đương
- #[Hidden([‘columns’])] — thay thế protected $hidden
- #[Visible([‘columns’])] — thay thế protected $visible
- #[Appends([‘accessors’])] — thay thế protected $appends
- #[Touches([‘relations’])] — thay thế protected $touches
- #[Connection(‘name’)] — thay thế protected $connection
Job Attributes – Queue Jobs
Queue Jobs cũng được hỗ trợ PHP Attributes đầy đủ, giúp cấu hình job behavior trở nên declarative và dễ đọc hơn.
Trước đây:
class ProcessOrder implements ShouldQueue
{
public $connection = 'redis';
public $queue = 'orders';
public $tries = 3;
public $timeout = 120;
}Với Laravel 13:
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Queue;
use Illuminate\Queue\Attributes\Tries;
use Illuminate\Queue\Attributes\Timeout;
#[Connection('redis')]
#[Queue('orders')]
#[Tries(3)]
#[Timeout(120)]
class ProcessOrder implements ShouldQueue
{
// Logic của job
}Một số Job Attributes hữu ích khác:
- #[Backoff([10, 60, 300])] — cấu hình thời gian chờ giữa các lần retry
- #[MaxExceptions(3)] — số exception tối đa trước khi đánh dấu failed vĩnh viễn
- #[FailOnTimeout] — đánh dấu job failed nếu timeout
- #[WithoutOverlapping] — không chạy song song với các job cùng loại
Command Attributes – Artisan Commands
Console Commands cũng được hưởng lợi từ PHP Attributes, cho phép khai báo signature và description trực tiếp trên class.
Trước đây:
class SyncDataCommand extends Command
{
protected $signature = 'sync:data {provider?}';
protected $description = 'Sync data from external provider';
}Với Laravel 13:
use Illuminate\Console\Command;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Attributes\Description;
#[Signature('sync:data {provider?}')]
#[Description('Sync data from external provider')]
class SyncDataCommand extends Command
{
// Logic của command
}Controller Attributes
Laravel 13 bổ sung hai controller attributes quan trọng: #[Middleware] và #[Authorize].
Trước đây bạn phải viết:
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('admin')->only(['destroy']);
}
}Với Laravel 13, bạn có thể viết gọn hơn:
use Illuminate\Routing\Controller;
use Illuminate\Routing\Attributes\Middleware;
use Illuminate\Routing\Attributes\Authorize;
#[Middleware('auth')]
class UserController extends Controller
{
#[Middleware('admin')]
#[Authorize('delete-users')]
public function destroy($id)
{
// Logic
}
}Chiến lược Migration thực tế
Không cần refactor tất cả cùng lúc. Hãy tiếp cận từ từ theo từng bước nhỏ.
Bước 1: Bắt đầu với model mới
Khi bạn tạo model mới trên Laravel 13, hãy sử dụng attributes ngay từ đầu. Đây là cách dễ nhất để áp dụng mà không ảnh hưởng đến code hiện có.
Bước 2: Convert khi đã chạm vào file
Khi bạn đang fix bug hoặc thêm feature cho một model cũ, hãy dành 5-10 phút để chuyển đổi sang attributes. Đừng refactor cả 50 models trong một PR – team sẽ khó review và nếu có lỗi, bạn sẽ không biết model nào gây ra.
Bước 3: Sử dụng IDE hỗ trợ
PhpStorm và VS Code với Intelephense đều hỗ trợ auto-import attributes. Khi bạn gõ tên attribute, IDE sẽ tự động thêm use statement.
Bước 4: Mix properties và attributes
Hệ thống hoàn toàn backward compatible. Bạn có thể dùng #[Table(‘users’)] nhưng vẫn giữ protected $fillable. Laravel sẽ resolve cả hai.
Tuy nhiên, nên chọn một style nhất quán cho mỗi file để code dễ đọc hơn.
Checklist Migration
Dưới đây là checklist từng bước để migration một file sang PHP Attributes:
- Đảm bảo PHP 8.3+ đang chạy (php -v)
- Đảm bảo Laravel 13 đã được cài đặt
- Chọn một file để migration (model, job, hoặc command)
- Thêm các use imports cần thiết cho từng attribute
- Di chuyển từng property sang attribute tương ứng
- Test để đảm bảo không có lỗi
- Commit với message rõ ràng, ví dụ: “refactor: convert User model to PHP Attributes”
Về performance, theo đánh giá từ cộng đồng Laravel [1], reflection trong PHP không có overhead đáng kể như nhiều người lo ngại. Attribute resolution xảy ra một lần khi application bootstrap, không ảnh hưởng đến request handling.
Nguồn tham khảo
- Laravel 13 PHP Attributes: A Practical Guide – Hafiz Riaz
- PHP Attributes in Laravel 13: The Ultimate Guide – Laravel Daily
- Laravel 13 PHP Attributes: Refactor in 10 Minutes – DEV Community
- Laravel 13 Deep Dive – DEV Community
- Laravel 13 Released – Laravel News
Các câu hỏi thường gặp
Tôi có bắt buộc phải dùng PHP Attributes không?
Không. PHP Attributes hoàn toàn tùy chọn. Laravel 13 backward compatible 100% – code cũ với protected properties vẫn hoạt động bình thường.
Tôi có thể mix properties và attributes trong cùng một model không?
Có thể. Bạn có thể dùng #[Table(‘users’)] nhưng vẫn giữ protected $fillable. Laravel sẽ resolve cả hai. Tuy nhiên, nên chọn một style nhất quán cho mỗi file.
PHP Attributes có ảnh hưởng đến performance không?
Không đáng kể. Reflection trong PHP không có overhead lớn như nhiều người lo ngại. Attribute resolution xảy ra một lần khi application bootstrap.
Laravel Shift có hỗ trợ migration tự động không?
Laravel Shift sẽ sớm cung cấp tính năng chuyển đổi tự động từ properties sang attributes. Tuy nhiên, vì đây là thay đổi tùy chọn, bạn có thể tự migrate theo tốc độ của mình.
Tôi nên bắt đầu migration từ đâu?
Bắt đầu với các model mới, sau đó convert các model cũ khi bạn đã chạm vào chúng để fix bug hoặc thêm feature. Không nên refactor tất cả cùng lúc.
Bạn đã thử migration sang PHP Attributes chưa? Chia sẻ kinh nghiệm nhé! Nếu có câu hỏi, để lại comment — mình sẽ hỗ trợ!
