Overview PHP attributes offer a native, machine-readable way to add metadata to classes, methods, and properties. In the context of Laravel, they replace traditional boilerplate methods like `booted()` or `newCollection()` with declarative tags. This shift moves configuration out of the logic flow and places it directly where it belongs: at the top of the class definition. It improves readability and makes the intent of a model or controller immediately clear to any developer opening the file. Prerequisites To follow this guide, you should have a solid grasp of PHP 8.0 or higher, as attributes were introduced in that version. You should also be comfortable with Laravel Eloquent models, the Service Container, and basic dependency injection patterns. Key Libraries & Tools * **PHP 8.2+**: The engine providing the attribute syntax and reflection capabilities. * **Laravel 11**: The framework implementing these specific attribute-driven features. * **Eloquent ORM**: The database layer where attributes define scopes and observers. Code Walkthrough Declarative Global Scopes Traditionally, you would apply a global scope inside a model's `booted` method. With attributes, you simply tag the class. ```php #[ScopedBy(ActiveScope::class)] class User extends Model { // No booted method required } ``` This tells Laravel to use Reflection to check for the `ScopedBy` attribute and apply the logic automatically. Model Observers and Collections Cleaning up the model continues by moving observers and custom collection definitions to the class header. ```php #[ObservedBy(UserObserver::class)] #[CollectedBy(UserCollection::class)] class User extends Model { } ``` This replaces the `observe()` call and the `newCollection()` method override, keeping the model body focused purely on business logic. Contextual Dependency Injection Attributes shine in controllers or form requests where you need specific implementations injected. Instead of manual binding in a ServiceProvider, use contextual attributes. ```php public function authorize( #[CurrentUser] User $user, #[RouteParameter('user')] User $userToUpdate ): bool { return $user->id === $userToUpdate->id; } ``` Here, `#[CurrentUser]` fetches the authenticated user, while `#[RouteParameter]` extracts a specific model from the Route Model Binding. Syntax Notes Attributes use the `#[ClassName]` syntax. They can accept positional or named arguments, much like a class constructor. Under the hood, Laravel utilizes PHP's `ReflectionClass` to find these attributes at runtime and execute the associated framework logic. Practical Examples Use these attributes when building multi-tenant applications where a `TenantScope` must be applied to dozens of models. It is also highly effective in complex API controllers where you need to inject specific configurations, such as a Redis cache implementation vs. a database implementation, directly into the method signature. Tips & Gotchas * **Performance**: While reflection has a tiny overhead, Laravel often caches these results, making the performance impact negligible. * **Namespace Imports**: Always remember to import the attribute class (e.g., `use Illuminate\Database\Eloquent\Attributes\ScopedBy;`) or your code will fail silently or throw an error. * **Readability**: Don't over-stack attributes. If a class needs ten different attributes, it might be a sign the class is handling too many responsibilities.
Laravel Eloquent
Products
- Oct 24, 2024
- Feb 8, 2024