CComponent覚え書き


Yiiの根幹を担う`CComponent`です。 <del>頭のCってなんだよ気持ち悪い。</del>
`CComponent`の挙動がわかるとYiiがよく見えてくるので予備知識としてあるといいかも。

##CComponentとは
Yiiのベースとなるクラスです。`framework/base/CComponent.php`に定義されています。Yiiの魔術回路が詰め込まれており、Yiiの中の多くのクラスが継承しています。モデルもARもコントローラーもイベントもコンソールコマンドもYiiにおいてはすべてコンポーネントです。

`CComponent`は

- プロパティ
- イベント
- ビヘイビア

に関する機能を持っています。

##プロパティ
例として下記のようなクラスを作ります。

```php:Hoge.php
<?php
class Hoge extends CComponent
{
	private $name;

	public function getName()
	{
		return $this->name;
	}

	public function setName($value)
	{
		$this->name = $value;
	}
}
```

このクラスは以下のように扱えます。

```php:
<?php
$hoge = new Hoge;
$hoge->name = 'john';
echo $hoge->name  //john
```

`name`はprivateなプロパティですが普通に扱っているように見えます。
実際は`CComponent`内のマジックメソッドから、プロパティ名に従ったそれぞれのgetter/setterが呼び出されています。

```php:変換ルール
<?php
$component->fuga        // => $component->getFuga()
$component->fuga = $val // => $component->setFuga($val)
```

これの何が便利なのかというと、通常と同じ簡易なインターフェイスで、getter/setterを定義することができ、処理を挟み込むことができるということです。
あるいは、getterだけしか存在しなければそれはreadOnlyなプロパティとして扱うことができます。

##イベント
`CComponent`はイベント機構も備えています。


```php:Fuga.php
<?php
class Fuga extends CComponent
{
    private $name;

    public function getName()
    {   
        $this->raiseEvent('onGetName', new CEvent($this));
        return $this->name;
    }   

    public function setName($value)
    {   
        $this->name = $value;
    }   

    public function onGetName($event)
    {   
        $this->raiseEvent('onGetName', $event);
    }   
}
```

先ほどのクラスに`onGetName()`が追加され、`getName()`内`raiseEvent()`が呼ばれるようにしました。

```php:
<?php
function piyo($event){
    echo 'am ';
}

class Poyo{
    static public function monyo($event)
    {
        echo 'a ';
    }
}

$hoge = new Hoge();
$hoge->name = 'john';

$hoge->onGetName = function($event){echo "I ";};
$hoge->onGetName = 'piyo';                  // => function poyo() return 'am '
$hoge->onGetName = array('Poyo', 'monyo'); // => Poyo::monyo() return 'a '

echo $hoge->name; //I am a john
```

`onGetName`に対してコールバックを連続して代入すると、`raiseEvent()`で呼ばれたイベントがすべてコールされます。
`Component::onEventName()`がフックポイントになり、発火のタイミングを指定すれば独自イベントも簡単に仕込むことができます。
Yiiで継承されているクラスはいたるところにフックポイントを用意してくれているので、外からの拡張も容易です。


##ビヘイビア
`CComponent`はビヘイビアと呼ばれる機構によって多重継承をサポートします

```php:Fuga.php
<?php
class Fuga extends CBehavior
{
    private $nickName;

    public function getNickName()
    {
        return $this->nickName;
    }

    public function setNickName($value)
    {
        $this->nickName = $value;
    }
}
```
ビヘイビアは`CBehavior`を継承する必要があります。（正確には`IBehavior`インターフェイスを持っていればいいのです）


```php:
<?php
$hoge = new Hoge();
$fugaBehavior = new Fuga();
$hoge->attachBehavior('nick', $fugaBehavior);

$hoge->nickName = 'criff';

echo $hoge->nickName;       //criff
echo $hoge->nick->nickName; //criff(上の行と同義)
```

ビヘイビアを`attachBehavior()`でアタッチしてやると、`$hoge`から`$fuga`のメンバを参照することができます。
内部的には、
1. アタッチしたときの名前でビヘイビアを格納 (この場合には`$hoge->nick`)
2. 呼び出された対象が自身にない場合、格納したビヘイビアのオブジェクトへ投げる
3. ビヘイビアに対象があれば呼ぶ。
という動作をしています。

単にコンポーネントにぶら下がったオブジェクトというだけですが、ビヘイビアとして渡すことで、あたかも通常プロパティのように利用することができるのです。


これらの機能が根底にあることで、Yiiは簡易さと拡張性を保持しています。Yiiを使う上で知っておいて損はないです。
特にプロパティは、ARでさらに拡張され、使い慣れてても「あれどっちの呼び出しが優先されるんだっけなー…」と混乱する時があるので細かい挙動を抑えておきたいです。
イベントとビヘイビアは実はそれほど使用頻度高くないですが、便利に使えるケースがあるので、公式のマニュアルなり読み込んでおくと役に立つと思います。

ちなみに[コレ](http://www.yiiframework.com/doc/guide/1.1/ja/basics.component)にもっと細かく書いてあります。のでそちらもどうぞ。