Laravel 13 marks a significant shift towards embracing PHP's attribute feature, offering a more declarative and cleaner way to configure various aspects of your application. This guide dives deep into the new attributes introduced, alongside existing ones, providing practical examples for Laravel and PHP developers.
It's important to note that these attributes are entirely optional. The traditional property-based syntax remains fully supported, ensuring backward compatibility and a smooth transition for existing projects.
New Eloquent Model Attributes
Laravel 13 introduces a suite of attributes that directly replace common Eloquent model properties, streamlining model definitions.
Mass Assignment Control
-
#[Fillable]Previously defined usingprotected $fillable, this attribute specifies which model attributes are mass assignable.use Illuminate\Database\Eloquent\Attributes\Fillable; #[Fillable(['title', 'body', 'status'])] class Post extends Model { } -
#[Guarded]Replacesprotected $guarded, defining attributes that are not mass assignable.use Illuminate\Database\Eloquent\Attributes\Guarded; #[Guarded(['id', 'is_admin'])] class User extends Model { } -
#[Unguarded]A simple marker attribute that disables mass-assignment protection entirely, equivalent toprotected $guarded = [];.use Illuminate\Database\Eloquent\Attributes\Unguarded; #[Unguarded] class Setting extends Model { }
Serialization Control
-
#[Hidden]Replacesprotected $hidden, specifying attributes to exclude from JSON serialization.use Illuminate\Database\Eloquent\Attributes\Hidden; #[Hidden(['password', 'remember_token'])] class User extends Model { } -
#[Visible]The inverse of#[Hidden], explicitly defining attributes to include in JSON serialization, replacingprotected $visible.use Illuminate\Database\Eloquent\Attributes\Visible; #[Visible(['id', 'name', 'email'])] class User extends Model { }
Relationship and Appending Configuration
-
#[Appends]Replacesprotected $appends, automatically appending accessor results to JSON output.use Illuminate\Database\Eloquent\Attributes\Appends; #[Appends(['full_name', 'is_active'])] class User extends Model { public function getFullNameAttribute(): string { return $this->first_name . ' ' . $this->last_name; } } -
#[Touches]Replacesprotected $touches, specifying parent models whose timestamps should be updated when the current model is saved.use Illuminate\Database\Eloquent\Attributes\Touches; #[Touches(['post'])] class Comment extends Model { public function post(): BelongsTo { return $this->belongsTo(Post::class); } }
Table and Connection Configuration
-
#[Table]A versatile attribute that consolidates configuration for$table,$primaryKey,$keyType,$incrementing,$timestamps, and$dateFormat.use Illuminate\Database\Eloquent\Attributes\Table; #[Table('blog_posts', key: 'post_id')] class Post extends Model { } #[Table( name: 'external_orders', key: 'uuid', keyType: 'string', incrementing: false, timestamps: false, )] class ExternalOrder extends Model { } -
#[Connection]Replacesprotected $connection, specifying the database connection to use for the model.use Illuminate\Database\Eloquent\Attributes\Connection; #[Connection('analytics')] class PageView extends Model { }
Queue / Job Attributes
Configure job behavior declaratively using attributes.
-
#[Tries]Sets the maximum number of times a job should be attempted, replacing$tries.use Illuminate\Queue\Attributes\Tries; #[Tries(3)] class ProcessPayment implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; } -
#[Timeout]Defines the job timeout in seconds, replacing$timeout.use Illuminate\Queue\Attributes\Timeout; #[Timeout(120)] class GenerateReport implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; } -
#[Backoff]Configures the delay between retries, supporting both fixed and exponential backoff strategies, replacing$backoff.use Illuminate\Queue\Attributes\Backoff; // Fixed backoff #[Backoff(30)] class SyncInventory implements ShouldQueue { // ... } // Exponential backoff #[Backoff([10, 30, 60])] class AnotherJob implements ShouldQueue { // ... }
This is just a glimpse of the new attribute-driven features in Laravel 13. As the framework evolves, expect more components to adopt this modern, declarative approach.