This article reprinted from www.laruence.com/2020/06/12/…

The Alpha version of PHP8 will be released in the next few days, including a number of new features, of course, the most important is the JIT, which I have been working on since 2013, after numerous setbacks and failures.

However, I’m not going to talk about JIT today. I’ll write a separate series like “JIT in PHP8” when PHP8 is released.

Today, I want to talk about Attributes. Why? Yesterday, I saw an article called “Understanding Attributes in PHP8” being forwarded by many groups. I don’t know what you’re talking about.

So I thought, in a short article, I would say what this is.

Postscript (2020/09/07), the latest RFC vote to change the annotation symbol from <<>> to #[], so this article has been updated to use the latest annotation symbol

Before WE get to annotations, let’s talk about old annotations. One of the things we see a lot in PHP projects is something like @param and @see:

    / * * *@param Foo $argument
    * @see https:/xxxxxxxx/xxxx/xxx.html
    */
    function dummy($Foo) {}
Copy the code

This is called a comment, and before PHP, @param and @see in a comment would have made no sense, and the entire section would have been saved as a function/method string called doc_comment.

If we want to analyze the meaning of this comment, we need to design some special syntax, such as @+name in chestnut, similar to @param, and then analyze the string ourselves to extract the corresponding information.

For example, to get information about the See annotation, we need to do something like:

    $ref = new ReflectionFunction("dummy");
    $doc = $ref->getDocComment();
    $see = substr($doc, strpos($doc."@see") + strlen("@see "));
Copy the code

Such string processing, relatively troublesome, but also more prone to error.

Attributes upgrades “comments” to “annotations” that support formatted content

Take the example above:

    #[Params("Foo", "argument")]
    #[See("https://xxxxxxxx/xxxx/xxx.html")]
    function dummy($argument) {}
Copy the code

When there are multiple annotations, you can also write:

    # [
    Params("Foo"."argument"),
    See("https://xxxxxxxx/xxxx/xxx.html")]function dummy($argument) {}
Copy the code

Now you can use Reflection to retrieve the formatted annotation. For example, we will now retrieve the See annotation:

    $ref = new ReflectionFunction("dummy");
    var_dump($ref->getAttributes("See") [0]->getName());
    var_dump($ref->getAttributes("See") [0]->getArguments());
Copy the code

Will output:

    string(3) "See"
    array(1) {[0] = >string(30) "https://xxxxxxxx/xxxx/xxx.html"
    }
Copy the code

A slightly more advanced use, of course, is that you can define what is called an “annotation class” :


      
#[Attribute(Attribute::TARGET_FUNCTION)]
class MyAttribute {
    public function __construct($name.$value) {
        var_dump($name);
        var_dump($value); }}Copy the code

You can then write something like this, noting the newInstance call:

#[MyAttribute("See", "https://xxxxxxxx/xxxx/xxx.html")]
function dummy($argument) {}$ref = new ReflectionFunction("dummy");

$ref->getAttributes("MyAttribute") [0]->newInstance();
Copy the code

If you run this code, you’ll See that MyAttribute’s __construct method is called with arguments like “See” and “https://xxx”.

See, you can instantiate an annotation, and then you can build your own annotation-as-configuration design based on that ability.

Attributes are written as follows:

#[Name]
#[Name(Arguments)]
#[Name(Argunment1, Arguments2, ArgumentN)]
 
#[Name1(Argument), Name2(Argument), Name3(Argument)]
Copy the code

You can then get the corresponding annotation using the Reflection series of PHP methods, according to getAttributes(“Name”), and you can get the Name by calling the getName method of the returned annotation, and the Arguments in parentheses using the getArguments method.

Further, if Name is an annotation class you define yourself, use #[Attribute(Attribute::TARGET_FUNCTION)], or:

TARGET_CLASS // Class annotation class
TARGET_FUNCTION // Function annotation class
TARGET_METHOD // Method annotation class
TARGET_PROPERTY // Attribute annotation class
TARGET_CLASS_CONSTANT // class constant annotation class
TARGET_PARAMETER // Parameter annotation class
TARGET_ALL
Copy the code

To indicate the target type of the annotation class application, then you can call newInstance to implement something like “new Name(Arguments)”.

Many people may ask, what the hell is this for?

To be honest, I’ve always been unimpressed by new features, but the Attributes are more or less a little 🙂