Table of Contents
Annotation syntax
Annotation class scope
Annotation namespace
Some other issues to pay attention to
Home Backend Development PHP8 How much do you know about php8 annotations?

How much do you know about php8 annotations?

Sep 15, 2021 pm 02:43 PM
php php8

Annotation syntax

#[Route]
#[Route()]
#[Route("/path", ["get"])]
#[Route(path: "/path", methods: ["get"])]
Copy after login

In fact, the syntax is very similar to the instantiated class, except that the new keyword is missing.

It should be noted that the annotation name cannot be a variable, but can only be a constant or constant expression

//实例化类
$route = new Route(path: "/path", methods: ["get"]);
Copy after login

(path: "/path", methods : ["get"]) is the new syntax of php8. When passing parameters, you can specify the parameter name and do not pass the parameters in the order of the formal parameters.

Annotation class scope

When defining an annotation class, you can use the built-in annotation class#[Attribute] to define the scope of the annotation class, or you can omit it,The scope is automatically defined by PHP dynamically based on usage scenarios.

Annotation scope list:

  • Attribute::TARGET_CLASS
  • Attribute::TARGET_FUNCTION
  • Attribute::TARGET_METHOD
  • Attribute::TARGET_PROPERTY
  • Attribute::TARGET_CLASS_CONSTANT
  • Attribute::TARGET_PARAMETER
  • Attribute::TARGET_ALL
  • Attribute::IS_REPEATABLE
When used, #[Attribute] is equivalent to #[Attribute(Attribute::TARGET_ALL)]. For convenience, the former is generally used.

1~7 are all easy to understand and correspond to classes, functions, class methods, class attributes, class constants, parameters, and everything respectively. The first 6 items can be combined at will using | or operators , such as Attribute::TARGET_CLASS | Attribute::TARGET_FUNCTION. (Attribute::TARGET_ALLcontains the first 6 items, but does not contain Attribute::IS_REPEATABLE).

Attribute::IS_REPEATABLE Set whether the annotation can be repeated, for example:

class IndexController
{
    #[Route('/index')]
    #[Route('/index_alias')]
    public function index()
    {
        echo "hello!world" . PHP_EOL;
    }
}
Copy after login

If Attribute::IS_REPEATABLE is not set, Route Two uses are not allowed.

As mentioned above, if the scope is not specified, PHP will dynamically determine the scope. How to understand? Example:

<?php

class Deprecated
{

}

class NewLogger
{
    public function newLogAction(): void
    {
        //do something
    }

    #[Deprecated(&#39;oldLogAction已废弃,请使用newLogAction代替&#39;)]
    public function oldLogAction(): void 
    {

    }
}

#[Deprecated(&#39;OldLogger已废弃,请使用NewLogger代替&#39;)]
class OldLogger
{

}
Copy after login

The above-mentioned custom annotation classDeprecated does not use the built-in annotation class#[Attribute] to define the scope, so when it modifies the class OldLogger, its scope is dynamically defined as TARGET_CLASS. When it modifies method oldLogAction, its scope is dynamically defined as TARGET_METHOD. In one sentence, where it is modified, its scope will be

It should be noted that after setting the scope, during the compilation phase, in addition to the built-in annotation class #[Attribute], custom annotation classes will not automatically check the scope. Unless you use the newInstance method of the reflection class ReflectionAttribute.

Example:

<?php

#[Attribute]
function foo()
{

}
Copy after login

An error will be reported hereFatal error: Attribute "Attribute" cannot target function (allowed targets: class), because of the role of the built-in annotation class The scope is TARGET_CLASS, which can only be used to modify classes and not functions. Because the scope of the built-in annotation class is only TARGET_CLASS, so cannot be modified repeatedly.

The scope of custom annotation classes will not be checked at compile time.

<?php 

#[Attribute(Attribute::TARGET_CLASS)]
class A1
{

}

#[A1] 
function foo() {}
Copy after login

This way no error will be reported. So what’s the point of defining scope? Let’s look at a comprehensive example.

<?php 

#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)]
class Route
{
    protected $handler;

    public function __construct(
        public string $path = &#39;&#39;,
        public array $methods = []
    ) {}

    public function setHandler($handler): self
    {
        $this->handler = $handler;
        return $this;
    }

    public function run()
    {
        call_user_func([new $this->handler->class, $this->handler->name]);
    }
}

class IndexController
{
    #[Route(path: "/index_alias", methods: ["get"])]
    #[Route(path: "/index", methods: ["get"])]
    public function index(): void
    {
        echo "hello!world" . PHP_EOL;
    }

    #[Route("/test")]
    public function test(): void 
    {
        echo "test" . PHP_EOL;
    }
}

class CLIRouter
{
    protected static array $routes = [];

    public static function setRoutes(array $routes): void
    {
        self::$routes = $routes;
    }

    public static function match($path)
    {
        foreach (self::$routes as $route) {
            if ($route->path == $path) {
                return $route;
            }
        }

        die('404' . PHP_EOL);
    }
}

$controller = new ReflectionClass(IndexController::class);
$methods = $controller->getMethods(ReflectionMethod::IS_PUBLIC);

$routes = [];
foreach ($methods as $method) {
    $attributes = $method->getAttributes(Route::class);

    foreach ($attributes as $attribute) {
        $routes[] = $attribute->newInstance()->setHandler($method);
    }
}

CLIRouter::setRoutes($routes);
CLIRouter::match($argv[1])->run();
Copy after login
php test.php /index
php test.php /index_alias
php test.php /test
Copy after login

The defined scope will only take effect when using newInstance. It is checked whether the scope defined by the annotation class is consistent with the actual modified scope. Other scenarios are not tested.

Annotation namespace

<?php

namespace {
    function dump_attributes($attributes) {
        $arr = [];
        foreach ($attributes as $attribute) {
            $arr[] = [&#39;name&#39; => $attribute->getName(), 'args' => $attribute->getArguments()];
        }
        var_dump($arr);
    }
}

namespace Doctrine\ORM\Mapping {
    class Entity {
    }
}

namespace Doctrine\ORM\Attributes {
    class Table {
    }
}

namespace Foo {
    use Doctrine\ORM\Mapping\Entity;
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\ORM\Attributes;

    #[Entity("imported class")]
    #[ORM\Entity("imported namespace")]
    #[\Doctrine\ORM\Mapping\Entity("absolute from namespace")]
    #[\Entity("import absolute from global")]
    #[Attributes\Table()]
    function foo() {
    }
}

namespace {
    class Entity {}

    dump_attributes((new ReflectionFunction('Foo\foo'))->getAttributes());
}

//输出:

array(5) {
  [0]=>
  array(2) {
    ["name"]=>
    string(27) "Doctrine\ORM\Mapping\Entity"
    ["args"]=>
    array(1) {
      [0]=>
      string(14) "imported class"
    }
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(27) "Doctrine\ORM\Mapping\Entity"
    ["args"]=>
    array(1) {
      [0]=>
      string(18) "imported namespace"
    }
  }
  [2]=>
  array(2) {
    ["name"]=>
    string(27) "Doctrine\ORM\Mapping\Entity"
    ["args"]=>
    array(1) {
      [0]=>
      string(23) "absolute from namespace"
    }
  }
  [3]=>
  array(2) {
    ["name"]=>
    string(6) "Entity"
    ["args"]=>
    array(1) {
      [0]=>
      string(27) "import absolute from global"
    }
  }
  [4]=>
  array(2) {
    ["name"]=>
    string(29) "Doctrine\ORM\Attributes\Table"
    ["args"]=>
    array(0) {
    }
  }
}
Copy after login

is consistent with the namespace of ordinary classes.

Some other issues to pay attention to

  • You cannot use the unpack syntax in the annotation class parameter list.
<?php

class IndexController
{
    #[Route(...["/index", ["get"]])]
    public function index()
    {

    }
}
Copy after login

Although the lexical parsing stage is passed, an error will be thrown during the compilation stage.

  • You can wrap lines when using annotations
<?php 

class IndexController
{
    #[Route(
        "/index",
        ["get"]
    )]
    public function index()
    {

    }
}
Copy after login
  • Annotations can be used in groups
<?php

class IndexController
{
    #[Route(
        "/index",
        ["get"]
    ), Other, Another]
    public function index()
    {

    }
}
Copy after login
  • Inheritance of annotations

Annotations can be inherited or overridden.

<?php

class C1
{
    #[A1]
    public function foo() { }
}

class C2 extends C1
{
    public function foo() { }
}

class C3 extends C1
{
    #[A1]
    public function bar() { }
}

$ref = new \ReflectionClass(C1::class);
print_r(array_map(fn ($a) => $a->getName(), $ref->getMethod('foo')->getAttributes()));

$ref = new \ReflectionClass(C2::class);
print_r(array_map(fn ($a) => $a->getName(), $ref->getMethod('foo')->getAttributes()));

$ref = new \ReflectionClass(C3::class);
print_r(array_map(fn ($a) => $a->getName(), $ref->getMethod('foo')->getAttributes()));
Copy after login

C3 inherits the foo method of C1 and also inherits the annotations of foo. And C2 covers the foo method of C1, so the annotation does not exist.

Recommended study: "PHP8 Tutorial"

The above is the detailed content of How much do you know about php8 annotations?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

PHP 8.4 Installation and Upgrade guide for Ubuntu and Debian PHP 8.4 Installation and Upgrade guide for Ubuntu and Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 brings several new features, security improvements, and performance improvements with healthy amounts of feature deprecations and removals. This guide explains how to install PHP 8.4 or upgrade to PHP 8.4 on Ubuntu, Debian, or their derivati

CakePHP Date and Time CakePHP Date and Time Sep 10, 2024 pm 05:27 PM

To work with date and time in cakephp4, we are going to make use of the available FrozenTime class.

CakePHP File upload CakePHP File upload Sep 10, 2024 pm 05:27 PM

To work on file upload we are going to use the form helper. Here, is an example for file upload.

Discuss CakePHP Discuss CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP is an open-source framework for PHP. It is intended to make developing, deploying and maintaining applications much easier. CakePHP is based on a MVC-like architecture that is both powerful and easy to grasp. Models, Views, and Controllers gu

CakePHP Creating Validators CakePHP Creating Validators Sep 10, 2024 pm 05:26 PM

Validator can be created by adding the following two lines in the controller.

CakePHP Logging CakePHP Logging Sep 10, 2024 pm 05:26 PM

Logging in CakePHP is a very easy task. You just have to use one function. You can log errors, exceptions, user activities, action taken by users, for any background process like cronjob. Logging data in CakePHP is easy. The log() function is provide

How To Set Up Visual Studio Code (VS Code) for PHP Development How To Set Up Visual Studio Code (VS Code) for PHP Development Dec 20, 2024 am 11:31 AM

Visual Studio Code, also known as VS Code, is a free source code editor — or integrated development environment (IDE) — available for all major operating systems. With a large collection of extensions for many programming languages, VS Code can be c

CakePHP Quick Guide CakePHP Quick Guide Sep 10, 2024 pm 05:27 PM

CakePHP is an open source MVC framework. It makes developing, deploying and maintaining applications much easier. CakePHP has a number of libraries to reduce the overload of most common tasks.

See all articles