注解的使用

<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);

/**
 * MyAttribute类(自定义注解类)
 */
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] // 声明MyAttribute类为注解类,且限制该注解类目标只能是类和方法
class MyAttribute
{
    private string $desc;

    public function __construct(string $desc)
    {
        $this->desc = $desc;
    }

    /**
     * @return string
     */
    public function getDesc(): string
    {
        return $this->desc;
    }
}

/**
 * MyClass类
 */
#[MyAttribute('这是MyClass类')] // 对MyClass类使用MyAttribute注解
class MyClass
{
    #[MyAttribute('这是MyClass::myMethod()方法')] // 对MyClass::myMethod()方法使用MyAttribute注解
    public function myMethod(): void
    {
        echo 'MyClass::myMethod()方法被调用';
    }
}


//========== 通过反射类获取该类的注解 ==========//
$reflectionClass = new ReflectionClass(MyClass::class); // 反射MyClass类
$attributes = $reflectionClass->getAttributes(); // 获取MyClass类的全部注解(该类只使用了MyAttribute注解)
foreach ($attributes as $attribute) {
    $attributeInstance = $attribute->newInstance(); // 创建注解类实例,由于该类只使用了MyAttribute注解,实际上就是MyAttribute实例
    $class1 = $reflectionClass->getName(); // 类名,就是MyClass
    $class2 = $attributeInstance::class; // 注解类名,就是MyAttribute
    $desc = $attributeInstance->getDesc();
    echo "{$class1}类的{$class2}注解desc为:$desc" . PHP_EOL;
    // MyClass类的MyAttribute注解desc为:这是MyClass类
}


//========== 通过反射方法获取该方法的注解 ==========//
$reflectionMethod = $reflectionClass->getMethod('myMethod'); // 反射MyClass::myMethod()方法
$attributes = $reflectionMethod->getAttributes(); // 获取MyClass::myMethod()方法的全部注解(该方法只使用了MyAttribute注解)
foreach ($attributes as $attribute) {
    $attributeInstance = $attribute->newInstance(); // 创建注解类实例,由于该方法只使用了MyAttribute注解,实际上就是MyAttribute实例
    $method = $reflectionMethod->getName(); // 方法名
    $class1 = $reflectionMethod->class; // 类名,就是MyClass
    $class2 = $attributeInstance::class; // 注解类名,就是MyAttribute
    $desc = $attributeInstance->getDesc();
    echo "$class1::$method()方法的{$class2}注解desc为:$desc" . PHP_EOL;
    // MyClass::myMethod()方法的MyAttribute注解desc为:这是MyClass::myMethod()方法
}


//========== 总结 ==========//
// 1、PHP注解本质仍然是注释,既然是注释就不会影响程序执行,而Java注解本身是程序,它会影响程序执行,这是PHP注解和Java注解最大不同。
// 2、PHP注解需要依赖反射将其解析才有意义,否则注解就只是一段普通注释而已。
// 3、注解的目标可以是函数、类、类常量、类属性、类方法等,只要是声明式代码都可以对其使用注解。
// 4、对目标使用注解的格式(无参)为“#[注解名]”,注解可以设置参数,示例:#[MyAttribute('张三', '男', 2003)]。
// 5、对目标使用注解其实很像创建注解类对象,只是省略了new关键字。
// 6、注解常见使用场景是路由和注入,尤其是注入,很多框架都会使用注解注入实现解耦。
// 7、注解一般是写框架或基于支持注解框架写业务才会使用,否则很少会使用。

Copyright © 2024 码农人生. All Rights Reserved