rhaco2のアクセサ、拡張アクセサについてのメモ

rhaco2は内容が変わりやすいフレームワークです。
この記事の公開日が過去な程、参考にはなるかもしれませんが、正確じゃなくなっている可能性が高くなります。
また、手探りで調べているところも多いので、元々正確じゃないかもしれません。

アクセサ

rhaco2のObjectと、それを継承するクラスで定義された便利なメソッドです。
マジックメソッドをふんだんに使って作られたこの機能は、クラスにプロパティを宣言することで、getter/setterを含む多くのプロパティへのアクセスを提供します。
rhaco2でのプログラミングでは、必ずこのアクセサを使ってコーディングしていく事になります。

プロパティ

アクセサは、基本的にはObjectに宣言されたプロパティに値を入れたり取り出したりするものです。

class Sample extends Object{
    static protected $__foo__ = 'type=mixed';
    protected $foo;
    protected $bar;
    private $fizz;

    public function buzz(){
        $this->foo(); // OK
        $this->bar(); // アノテーションは省略してもOK
        $this->fizz(); // privateなのでだめ
        $this->foobar(); // 宣言されてないのでだめ
    }
}

アクセサが使えるプロパティは、protected以上で宣言されたもので、privateや未宣言だと使えません。
rhaco2のObjectにはアノテーション機能があるけど、これは省略してもアクセサは使えます。
プロパティがprotectedでもアクセサ自体はpublicです。

標準のアクセサ

Objectにて宣言されている標準のアクセサは全部*1で8個あります。

$this->foo('bar')
setter。
$this->foo()
getter。
$this->in_foo()
配列から値を取り出す。
$this->rm_foo()
プロパティの値を削除。配列の場合は、引数でキーを指定できます。
$this->ar_foo()
配列じゃないプロパティも配列として返す*2。配列の場合はそのままだけど、引数*3を使ってarray_slice()の様なスライスが出来ます。
$this->fm_foo()
プロパティの中身を整形。プロパティのtype*4がmixedだと無意味。
$this->is_foo()
プロパティの妥当性をチェック。大抵は値があればtrueで、未定義やnullだとfalseになります。
$this->label_foo()
プロパティに名前を付ける。エラーメッセージの出力などに使うらしい。

プロパティが配列かどうかや、アノテーションのtypeによって動きが違ったりするのもあるけど、大体こんな感じの機能です。

$this->foo('bar')
protected function __set__($args,$param)
$this->foo()
protected function __get__($arg,$param)
$this->in_foo()
protected function __in__($args,$param,&$var)
$this->rm_foo()
protected function __rm__($args,$param,&$var)
$this->ar_foo()
protected function __ar__($args,$param,&$var)
$this->fm_foo()
protected function __fm__($args,$param,&$var,&$obj)
$this->is_foo()
protected function __is__($args,$param,&$var)
$this->label_foo()
protected function __label__($args,$param,&$var,&$obj)

アクセサの実体は、Objectの各メソッドになってます。

拡張アクセサ

Objectを継承したクラスであれば、アクセサを拡張して、自分のアクセサを作る事が出来ます。

$this->foo_bar()
protected function __foo__($args,$param,&var,&$obj)
<?php require dirname(__FILE__)."/__settings__.php";
class Foo extends Object{
    static protected $__foo__ = 'type=string';
    static protected $__foobar__ = 'type=string';
    protected $foo;
    protected $foobar;
    protected function __foo__($args, $param){
        $arg = isset($args[0]) ? $args[0] : '';
        return $param->name.$arg;
    }
}
$d = array();
$foo = new Foo();
$d[] = $foo->foo_foo(); //'foo'
$d[] = $foo->foo_foo('bar'); //'foobar'
$d[] = $foo->foo_foobar('buz'); //'foobarbuz'
Log::d($d);

サンプルとして的当すぎるけど、こんな感じで拡張アクセサが使えます。
アクセサと言いつつプロパティ*5にアクセスしてないですけど。

$args
アクセサとして呼んだ際に渡される引数
$param
アクセサからアクセスされたプロパティの構成を表すオブジェクト*6
&$var
プロパティの中身
&$obj
どのオブジェクトのメソッドとして、アクセサを呼んだか。この場合はFooクラスのインスタンス

拡張アクセサを作る際、こんな引数が利用できます。

プロパティ毎の拡張

さらに、プロパティ毎に違った動きをさせるように拡張が出来ます。

protected function __foo_bar__($args)

        protected function __set_current__($value){
                $value = intval($value);
                $this->current = ($value === 0) ? 1 : $value;
                $this->offset = $this->limit * round(abs($this->current - 1));
        }
        protected function __set_total__($total){
                $this->total = intval($total);
                $this->last = ($this->total == 0 || $this->limit == 0) ? 0 : intval(ceil($this->total / $this->limit));
        }
http://code.google.com/p/tokushima/source/browse/spl/Paginator.php?repo=core#216

ちょっとサンプルがsetterなので特殊ですが、$currentと$totalの2つのプロパティに対しての__set__アクセサの動きを変えています。
プロパティ毎の拡張の場合、渡される引数は $args だけみたいです。*7

$this->current();
$this->total();

ちなみに、このサンプルの場合は、元が__set__なので、呼び方はこうなります。

アクセサぽいけどアクセサじゃないもの

  1. protected function __add__()
  2. protected function __sub__()
  3. protected function __mul__()
  4. protected function __div__()
http://tokushimakazutaka.com/detail/216
  1. protected function __new__()
  2. protected function __init__()
  3. protected function __del__()
http://tokushimakazutaka.com/detail/214
  1. protected function __str__()
http://tokushimakazutaka.com/detail/220
  1. protected function __import__()
  2. protected function __shutdown__()
http://tokushimakazutaka.com/detail/215
  1. protected function __hash__()
http://tokushimakazutaka.com/detail/217
  1. protected function __cp__()
http://tokushimakazutaka.com/detail/219
  1. protected function __clone__()
http://tokushimakazutaka.com/detail/221

rhaco2のソースコードを眺めてると、他にもアクセサっぽい感じで宣言されてるメソッドが色々あります。
これがアクセサなのか別の機能なのか、よく分かりませんが、とりあえず上記のアクセサとは違うものだと思います。
それぞれ、特別な意味を持ったメソッドだとは思いますが、とりあえず調べきれないので目に付いたのを並べて置くだけに。

*1:今のところ

*2:配列でも配列じゃなくても配列が返るので、中身に関わらずforeachに渡したりする時に使うらしいです。

*3:int $offset[, int $limit]

*4:rhaco2のアノテーションで設定するもの

*5:$foo, $foobar

*6:プロパティ名とかtypeとか

*7:この辺になってくるとちょっと追いきれてません。