Tasting the cake with attributes
Attributes is a declarative way to pass information about the behaviors of various elements like classes, methods, properties, and even method parameters in your programs. In fact, attributes are used for adding metadata to existing code, and could be used as a way to reduce visual debt, and this way simplifies how code looks like.
Defining an attribute
An attribute is simply an object whose class inherits from the Attribute class. However, attributes are not used in the same way as a typical object. They often add some additional semantics about the class or method, or to toggle behavior on or off. Some attributes specify functionality. For example, an attribute may contain a method that defines security behavior.
Declaring Attributes
The attribute itself may be declared as a class. This is validated only when the attribute is fetched, and not immediately when the code is parsed.
A PHP attribute is a class, declared with #[Attribute]
attribute.
In the following example we define an attribute class which allows us to specify what methods are allowed for controller actions.
Take note that in PHP 8 you can declare properties directly in class constructors, which is really handy for data classes.
Consuming reflection API to define meta behaviors
Just defined attributes have not added new code logic. To add new behavior we should implement it. Attributes could be fetched using the reflection API. PHP engine knows about attributes but does not instantiate it’s classes, so we have to do it ourselves. Reflection provides getAttributes()
methods to fetch a list of associated attributes.
The following example shows how we can add permissions checks for controller actions using attributes. In this example, the code is stored in beforeFilter of the controller class itself, but it could be an AppController or more generic solution.
Where to use Attributes
Here are some areas where web frameworks could use attributes:
- Routes definition for the controller methods;
- Validation rules as attributes for entity properties;
- Smart object serialization, which defined as properties attributes
- Security rules defined for classes and methods.
- Static code analyzers.
- IDE code hinting.
The attributes are very handy and powerful, they could reduce visual debt and improve code quality. Hopefully this helps with your future projects!