注解概覽

(PHP 8)

注解功能提供了代碼中的聲明部分都可以添加結(jié)構(gòu)化、機(jī)器可讀的元數(shù)據(jù)的能力, 注解的目標(biāo)可以是類、方法、函數(shù)、參數(shù)、屬性、類常量。 通過 反射 API 可在運(yùn)行時(shí)獲取注解所定義的元數(shù)據(jù)。 因此注解可以成為直接嵌入代碼的配置式語言。

通過注解的使用,在應(yīng)用中實(shí)現(xiàn)功能、使用功能可以相互解耦。 某種程度上講,它可以和接口(interface)與其實(shí)現(xiàn)(implementation)相比較。 但接口與實(shí)現(xiàn)是代碼相關(guān)的,注解則與聲明額外信息和配置相關(guān)。 接口可以通過類來實(shí)現(xiàn),而注解也可以聲明到方法、函數(shù)、參數(shù)、屬性、類常量中。 因此它們比接口更靈活。

注解使用的一個(gè)簡單例子:將接口(interface)的可選方法改用注解實(shí)現(xiàn)。 我們假設(shè)接口 ActionHandler 代表了應(yīng)用的一個(gè)操作: 部分 action handler 的實(shí)現(xiàn)需要 setup,部分不需要。 我們可以使用注解,而不用要求所有類必須實(shí)現(xiàn) ActionHandler 接口并實(shí)現(xiàn) setUp() 方法。 因此帶來一個(gè)好處——可以多次使用注解。

示例 #1 用注解實(shí)現(xiàn)接口的可選方法

<?php
interface ActionHandler
{
    public function 
execute();
}

#[Attribute]
class SetUp {}

class 
CopyFile implements ActionHandler
{
    public 
string $fileName;
    public 
string $targetDirectory;

    
#[SetUp]
    
public function fileExists()
    {
        if (!
file_exists($this->fileName)) {
            throw new 
RuntimeException("File does not exist");
        }
    }

    
#[SetUp]
    
public function targetDirectoryExists()
    {
        if (!
file_exists($this->targetDirectory)) {
            
mkdir($this->targetDirectory);
        } elseif (!
is_dir($this->targetDirectory)) {
            throw new 
RuntimeException("Target directory $this->targetDirectory is not a directory");
        }
    }

    public function 
execute()
    {
        
copy($this->fileName$this->targetDirectory '/' basename($this->fileName));
    }
}

function 
executeAction(ActionHandler $actionHandler)
{
    
$reflection = new ReflectionObject($actionHandler);

    foreach (
$reflection->getMethods() as $method) {
        
$attributes $method->getAttributes(SetUp::class);

        if (
count($attributes) > 0) {
            
$methodName $method->getName();

            
$actionHandler->$methodName();
        }
    }

    
$actionHandler->execute();
}

$copyAction = new CopyFile();
$copyAction->fileName "/tmp/foo.jpg";
$copyAction->targetDirectory "/home/user";

executeAction($copyAction);