Skip to main content

What are PHP attributes?

PHP attributes (PHP Attributes) are a native metadata syntax introduced in PHP 8.0. They let you attach meta-information to classes, methods, properties, and functions using the #[AttributeName] syntax. Laravel actively adopts PHP attributes throughout the framework, allowing you to declare job and Eloquent model configuration in a declarative style. In Laravel 13 (v13.2.0), queue attributes gained the ability to accept enums. Instead of class properties or method overrides, attributes let you write cleaner, more readable code.
Attributes require PHP 8.0 or later. Since Laravel 13 requires PHP 8.3 or higher, attributes are available in every supported environment.

Queue attributes

All queue job attributes live in the Illuminate\Queue\Attributes namespace.

#[Queue] — specify the queue name

Specifies the default queue name the job is dispatched to.
Since v13.2.0, you can pass an enum instead of a string.
The #[Queue] attribute targets Attribute::TARGET_CLASS, so it can only be applied to classes.

#[Connection] — specify the connection

Specifies the default queue connection the job uses.
Enums work here as well.

#[Backoff] — specify retry backoff time

Specifies the wait time in seconds before retrying a failed job. Pass multiple values to use a different wait time for each retry (variadic argument support).
Looking at the Backoff class implementation, it accepts variadic arguments.
A single value is stored as int; multiple values are stored as array.

#[Tries] — specify the retry count

Specifies the maximum number of times a failed job should be retried.

#[Timeout] — specify the timeout

Specifies the maximum execution time in seconds. The job is forcefully terminated if it exceeds this limit.

#[MaxExceptions] — specify the maximum exception count

Marks a job as failed after the specified number of exceptions have been thrown. Use together with #[Tries].

#[UniqueFor] — specify the uniqueness period

Specifies the lock duration in seconds to prevent duplicate job execution. Use together with ShouldBeUnique.

#[DeleteWhenMissingModels] — delete when the model is missing

When the Eloquent model a job depends on cannot be found, the job is deleted (skipped) instead of marked as failed.

#[WithoutRelations] — exclude relations from serialization

Prevents model relations from being included when serializing the job. This reduces the payload sent to the queue.

#[FailOnTimeout] — mark as failed on timeout

Records the job as failed when a timeout occurs (by default, timeouts are not recorded as failures).

Combining multiple queue attributes

You can combine these attributes to declare a job’s behavior entirely through attributes.

Eloquent attributes

Eloquent model attributes live in the Illuminate\Database\Eloquent\Attributes namespace. Laravel 13 added a large number of new attributes.

#[ScopedBy] — specify global scopes

Specifies the global scope classes to apply to a model automatically via an attribute. Supports inheritance and allows multiple scopes using the IS_REPEATABLE flag.
To apply multiple scopes, repeat the attribute or pass an array.
Comparison with the traditional booted() method:

#[ObservedBy] — specify observers

Specifies the observer classes to associate with a model via an attribute. Like ScopedBy, it is IS_REPEATABLE.
You can specify multiple observers too.
This eliminates the need to register observers in AppServiceProvider.

#[UseEloquentBuilder] — specify a custom query builder

Specifies the custom Eloquent builder the model should use via an attribute.

#[CollectedBy] — specify a custom collection

Specifies the custom collection class to use for the model’s collection via an attribute.

#[Table] — configure table settings in one place

Lets you specify multiple table-related settings — table name, primary key, timestamps, and more — with a single attribute.
Options available through the Table attribute:

#[Scope] — define a method as a local scope

Lets you define a method as an Eloquent local scope without the scope prefix.

#[UseFactory] — specify a factory class

Specifies the custom factory class the model should use via an attribute.

Other Eloquent attributes

Enum support (added in v13.2.0)

In v13.2.0, #[Queue] and #[Connection] gained the ability to accept enums. This lets you specify queues and connections in a type-safe manner using PHP enums instead of string literals.
Using enums prevents typos in queue and connection names and enables IDE auto-completion. It is convenient for centrally managing all queue names and connection names across your application.

Comparison with traditional class properties

Benefits of attributes

  • Declarative — A glance at the top of the class reveals the job’s behavior
  • Type-safe — Enums enable IDE completion and type checking
  • Compatible with inheritance — Child classes can override parent class attributes
  • Less code — No need for property declarations or method overrides

Drawbacks of attributes

  • Cannot use dynamic values — Attribute arguments are compile-time constants only; variables and config values are not supported
  • Learning curve — Teams may need time to get comfortable with PHP 8 attribute syntax

When dynamic values are required

Use the traditional method override approach when you need to determine a value at runtime.
Attributes are parsed at PHP compile time. You cannot use runtime values such as config() or env(). When dynamic configuration is needed, continue using class properties or methods.

How it works internally

Laravel uses the Reflection API internally to read attributes. When the queue worker dispatches a job, the ReadsQueueAttributes trait (included in InteractsWithQueue) uses reflection to detect attributes and sets the corresponding properties.
Eloquent model attributes are similarly read via reflection at the equivalent of Model::booted().

Next steps

Intermediate: Queues and jobs

Learn the basics of Laravel’s queue system.

PHP Reflection API

A deep dive into the Reflection API that Laravel uses internally to read attributes.
Last modified on May 11, 2026