PHP Attributes in Laravel 13: A Comprehensive Guide
Laravel #Laravel #PHP #Attributes #Eloquent #Queues

PHP Attributes in Laravel 13: A Comprehensive Guide

3 min read Mohamed Said Mohamed Said

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 using protected $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] Replaces protected $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 to protected $guarded = [];.

    use Illuminate\Database\Eloquent\Attributes\Unguarded;
    
    #[Unguarded]
    class Setting extends Model
    {
    }
    

Serialization Control

  • #[Hidden] Replaces protected $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, replacing protected $visible.

    use Illuminate\Database\Eloquent\Attributes\Visible;
    
    #[Visible(['id', 'name', 'email'])]
    class User extends Model
    {
    }
    

Relationship and Appending Configuration

  • #[Appends] Replaces protected $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] Replaces protected $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] Replaces protected $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.


Found this useful?

Frequently Asked Questions

3 questions
Q01 Are PHP Attributes in Laravel 13 breaking changes?
No, the new PHP Attributes in Laravel 13 are optional. The traditional property-based syntax for Eloquent models and queue jobs remains fully supported.
Q02 What Eloquent model properties can be replaced by attributes in Laravel 13?
In Laravel 13, attributes can replace properties like `$fillable`, `$guarded`, `$hidden`, `$visible`, `$appends`, `$table`, `$primaryKey`, `$keyType`, `$incrementing`, `$timestamps`, `$dateFormat`, `$connection`, and `$touches`.
Q03 How do PHP Attributes improve Queue Job configuration in Laravel 13?
Laravel 13 allows configuring Queue Jobs using attributes like `#[Tries]`, `#[Timeout]`, and `#[Backoff]`, providing a more declarative and readable way to manage job retry logic and execution parameters.

Continue reading

More Articles

View all