PHP のトレイト – 実際の例やベストプラクティスはありますか? [closed] 質問する

PHP のトレイト – 実際の例やベストプラクティスはありますか? [closed] 質問する

特性PHP 5.4 で追加された最も大きな機能の 1 つです。私は構文を知っており、ログ記録、セキュリティ、キャッシュなどの一般的な機能に対する水平的なコード再利用など、特性の背後にある考え方を理解しています。

しかし、自分のプロジェクトで特性をどのように活用するかはまだわかりません。

すでに特性を使用しているオープンソース プロジェクトはありますか? 特性を使用してアーキテクチャを構築する方法に関する優れた記事や読み物はありますか?

ベストアンサー1

受け入れられている良い/ベスト プラクティスを学ぶには、しばらくの間、Trait を持つ言語を調べる必要があると思います。Trait に関する私の現在の意見は、同じ機能を共有する他のクラスで複製する必要があるコードにのみ Trait を使用するべきだということです。

Logger 特性の例:

interface Logger
{
    public function log($message, $level);    
}

class DemoLogger implements Logger
{
    public function log($message, $level)
    {
        echo "Logged message: $message with level $level", PHP_EOL; 
    }
}

trait Loggable // implements Logger
{
    protected $logger;
    public function setLogger(Logger $logger)
    {
        $this->logger = $logger;
    }
    public function log($message, $level)
    {
        $this->logger->log($message, $level);
    }
}

class Foo implements Logger
{
    use Loggable;
}

そして、(デモ

$foo = new Foo;
$foo->setLogger(new DemoLogger);
$foo->log('It works', 1);

特性を使用する際に考慮すべき重要な点は、特性はクラスにコピーされるコードの一部にすぎないということだと思います。これにより、たとえばメソッドの可視性を変更しようとすると、簡単に競合が発生する可能性があります。

trait T {
    protected function foo() {}
}
class A { 
    public function foo() {}
}
class B extends A
{
    use T;
}

上記はエラーになります(デモ同様に、トレイトで宣言され、使用クラスでも既に宣言されているメソッドは、クラスにコピーされません。例:

trait T {
    public function foo() {
    return 1;
}
}
class A { 
    use T;
    public function foo() {
    return 2;
}
}

$a = new A;
echo $a->foo();

2を印刷します(デモこれらはエラーを見つけにくくするため避けたいものです。また、それを使用するクラスのプロパティやメソッドを操作するものを特性に配置することも避けたいでしょう。例:

class A
{
    use T;
    protected $prop = 1;
    protected function getProp() {
        return $this->prop;
    }
}

trait T
{
    public function foo()
    {
        return $this->getProp();
    }
}

$a = new A;
echo $a->foo();

作品(デモ) しかし、今では特性は A と密接に結合されており、水平再利用という概念全体が失われています。

に従うとインターフェース分離の原則小さなクラスやインターフェースがたくさんあるでしょう。そのため、Traitsはあなたが言及したものに最適な候補となります。横断的な懸念ただし、オブジェクトを構成することはできません (構造的な意味で)。上記の Logger の例では、特性は完全に分離されています。具体的なクラスに依存しません。

使える集約/構成(このページの他の場所で示されているように) 同じ結果クラスを実現できますが、集約/構成を使用する欠点は、ログに記録できる各クラスにプロキシ/デリゲータ メソッドを手動で追加する必要があることです。特性を使用すると、定型句を 1 か所に保持し、必要な場所に選択的に適用できるため、この問題がうまく解決されます。

注: 特性は PHP の新しい概念であるため、上記の意見はすべて変更される可能性があります。私自身はまだこの概念を評価する時間があまりありません。しかし、皆さんが考えるきっかけとなるような内容になれば幸いです。

おすすめ記事