PHP Video Tutorial: PHP 8: Attributes
In this video I invite you to discover one of the new features of PHP 8: Attributes.
Annotations but native
The concept of attributes is not new and if you are working with doctrine or symfony you have probably encountered it in another form: annotations.
/ **
* @Route ("/ demo")
** /
function demo () {
return 'Hello everyone!';
}
The principle is to add metadata to a method, a property, a function or a class. The problem was that until now there was no native way to handle things and we had to use a third party library. PHP 8 therefore introduces a new syntax and new terminology Attribute (not to be confused with annotations).
# (Route ("/ demo"))
function demo () {
return 'Hello everyone!';
}
The syntax is different but the principle is the same.
Create an attribute
To create an attribute, just create a class which itself will have the attribute Attribute
. This attribute can receive as a parameter the type of content that can receive the attribute.
path;
}
public function getMethod (): string
{
return $ this-> method;
}
}
You can then use your attribute wherever you want
# (Route ('/ api'))
class HelloController
{
# (Route ('/ hello / {name}'))
public function hello (string $ name) {
return <<< HTML
Hello {$ name}
HTML;
}
# (Route ('/ goodbye / {name}', method: 'post'))
public function goodbye (Response $ response, string $ name) {
$ response-> getBody () -> write ("Goodbye, $ name");
return $ response;
}
}
Finally, you will be able to read the attributes using the PHP reflection API thanks to the method getAttributes ()
.
$ class = new ReflectionClass (HelloController :: class);
$ routeAttributes = $ class-> getAttributes ( App Attribute Route :: class);
You would then get an array of ReflectionAttribute
containing the name of your attributes as well as the arguments to pass to it. We will especially note the possibility of recovering an instance of our attribute using the method newInstance ()
.
$ class = new ReflectionClass (HelloController :: class);
$ routeAttributes = $ class-> getAttributes ( App Attribute Route :: class);
if (! empty ($ routeAttributes)) {
// Here we have our Route instance built with the right arguments
$ route = $ routeAttributes (0) -> newInstance ();
}
From there it's up to you to imagine the possible uses.
Some avenues of use
Now that we have seen the principle, we can ask ourselves the question of the use cases of such a feature. Also here are some avenues that can be explored.
EventListener
For an event listener, annotations can be used to define which event responds to a specific method
class CommentEventListener {
# (SubscribeTo (CommentCreatedEvent :: class))
public function onCreated (CommentCreatedEvent $ event) {
}
# (
SubscribeTo (CommentDeletedEvent :: class),
SubscribeTo (CommentBlacklisted :: class)
)
public function onDelete (CommentCreatedEvent $ event) {
}
}
A control system
It can be used to automatically record orders
class ServerCommand {
# (Command ("app: run", arguments: ('port', 'host')))
public function build (IO $ io, array $ args) {
}
}
Data validation
class Post {
# (
Validation Unique,
Validation Email,
)
private string $ email;
# (
Validation NotBlank,
Validation Length (min: 5, max: 12),
)
private string $ username;
}
Connection with the database
class Post {
# (ORM Column (name: 'email', type: 'VARCHAR', length: 255))
private string $ email;
}