12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

YiiAdvent Calendar 2012

Day 1

CComponent覚え書き

Last updated at Posted at 2012-12-01

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

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

CComponent

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

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

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

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

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

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

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

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

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

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

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

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

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
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はビヘイビアと呼ばれる機構によって多重継承をサポートします

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
$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でさらに拡張され、使い慣れてても「あれどっちの呼び出しが優先されるんだっけなー…」と混乱する時があるので細かい挙動を抑えておきたいです。
イベントとビヘイビアは実はそれほど使用頻度高くないですが、便利に使えるケースがあるので、公式のマニュアルなり読み込んでおくと役に立つと思います。

ちなみにコレにもっと細かく書いてあります。のでそちらもどうぞ。

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?