PHPのTraitをやたらと使って感じたこと

以前、php5.4のプロジェクトに関わっていて、
そこのプロジェクトの方針でやたらとTraitを作っていたが、Traitの多用は「鬼門」だと正直思った。

class MyModel extends BaseModel
{
    use User;
    use Photo;
    use Album;
    use Relation;
    //....
    //....

    public function getData($id)
    {
        $tmp = $this->getFriendList($id); //どのTraitに実装されているか
        return $this->getPhotoSet($tmp); //調べるのが結構たいへん!
    }
}

NetBeansの場合はtraitのコード補完・関数ジャンプの機能があるからまだ楽だけど、
それでも実装があちこちに飛んでしまうのは階層の深い継承と同じストレスがあるし、
Traitの関数名を迂闊に変えて、他のTraitの関数と名前が衝突してしてコンパイルエラーが起こるので、多重継承と同じストレスもある

しかし、継承を使わずにプロパティにアクセス出来る実装を使いまわせるのは便利だった。

例えば、SPLにあるArrayAccessインターフェイスとかはTraitにしたほうが便利なのではないかと思う。

/**
 * ArrayAccessで典型的な処理をTraitで実装
 */
trait ArrayAccessHelper
{
    public function setProerty($offset, $value)
     {
        if (!empty($offset)) {
            $this->$offset = $value;
        }
    }
    public function proertyExists($offset) {
        return property_exists($this, $offset);
    }
    public function unsetProerty($offset) {
        unset($this->$offset);
    }
    public function getProerty($offset) {
        return property_exists($this, $offset) ? $this->$offset : null;
    }
}

/**
 * 上記をArrayAccessインターフェイスと合わせて使う
 */
class ArrayObj implements arrayaccess
{
    use ArrayAccessHelper;

    public function offsetSet($offset, $value)
    {
        return $this->setProerty($offset, $value);
    }
    public function offsetExists($offset)
    {
        return this->proertyExists($offset]);
    }
    public function offsetUnset($offset)
    {
        return $this->unsetProerty($offset);
    }
    public function offsetGet($offset) {
        return $this->getProerty($offset]);
    }
}

まぁこのやり方でも、インターフェイスの実装は必要なだけど、幾つものクラスにインタフェイスを実装するときはこの方法でタイプの量をかなり減らせる。
(※1)

あと、以前のプロジェクトではCodeIgniterのModelにTraitを使っていた。

コネクションを保持するのはCI_Model の$db
特定のテーブルのアクセスはメソッドはTraitにまとめる
アプリ内で使用するModelは上記2つを合わせて構築する
上記のルールでテーブルへのアクセス処理をかなり共通化出来たのですが、
その代わり最初に書いた問題も露呈指摘たのでTraitの使い処は難しい。


(※1) ArrayAccessを実装したクラスをを継承したほうが手っ取り早い事に気づいた、、、