アトリビュートの概要

(PHP 8)

アトリビュートを使うと、 コンピューターが解析できる構造化されたメタデータの情報を、 コードの宣言時に埋め込むことができます。 つまり、クラス、メソッド、関数、プロパティ、クラス定数にアトリビュートを指定することができます。 アトリビュートで定義されたメタデータは、 実行時に リフレクションAPI を使って調べることが出来ます。 よって、アトリビュートは、 コードに直接埋め込むことが出来る、 設定のための言語とみなすことができます。

アトリビュートを使うと、機能の抽象的な実装と、アプリケーションでの具体的な利用を分離できます。 この点でアトリビュートは、インターフェイスとその実装と比較できます。 インターフェイスとその実装はコードに関する情報ですが、 アトリビュートはコードの追加情報と設定に注釈を付けるものです。 インターフェイスはクラスによって実装できますが、 アトリビュートはメソッドや関数、引数、プロパティ、クラス定数で宣言できます。 よって、アトリビュートはインターフェイスより柔軟です。

アトリビュートの使い方の簡単な例として、 必須でないメソッドを持つインターフェイスを、 アトリビュートを使うように変換するコードを示します。 アプリケーションの操作を表現する ActionHandler があるとします。 この ActionHandler の実装は、セットアップが必須なものもありますが、 そうでないものもあります。 ActionHandler を実装する全てのクラスで setUp() メソッドを必須とする代わりに、 アトリビュートを使うようにしてみましょう。 このアプローチの利点のひとつは、 アトリビュートを複数回使えることです。

例1 アトリビュートを使い、インターフェイスのオプションのメソッドを実装する

<?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);
関連キーワード:  アトリビュート, 概要, 実装, コード, クラス, メソッド, ActionHandler, メタデータ, 宣言, アプリケーション