ログ日記

作業ログと日記とメモ

SPLのIteratorIteratorを使う

foreachで少しだけ表示を変えたい、イテレータのcurrentを表示のために少しだけ変えたい、という場合。
単純にイテレータを継承すると関係がややこしくなるので外部から書き換えたい。
というときのためのクラス。

<?php
class Iterator_Current extends IteratorIterator
{
    private $callback;
    public function __construct($iterator, $callback)
    {
        parent::__construct($iterator);
        $this->callback = $callback;
    }

    public function current()
    {
        $arg = parent::current();
        return call_user_func($this->callback, $arg);
    }
}

IteratorIteratorを使ってる例を検索してみたけれど出てこない。こんな使い方で合ってるのかな。



例えばアクションクラスから、これまでに作ったイテレータを使いたいけど少しだけ表示を変えたい場合は

<?php
class SomeAction
{
    /** @var Iterator ビューのための変数 */
    public $items;

    public function execute()
    {
        /* DBのitemテーブルからリストを表示するイテレータ */
        $iterator = new ItemIterator();

        /* イテレータの一部を書き換えてビュー用に設定。 */
        $this->items = new Iterator_Current($iterator, array($this, 'stripe'));
    }

    /**
     * テーブル縞模様表示のためにスタイルシートのクラスを設定する。
     *
     * @param Vo $obj itemデータが入っている構造体ぽいクラス。
     * @return Vo
     */
    public function stripe($obj)
    {
        if ($obj->id %2)
            $obj->class = 'foo';
        else
            $obj->class = 'bar';
        return $obj;
    }
}

とかする。
こういう表示のための細かいコードはイテレータを継承して云々じゃなくてアクションに書いた方がいいし、これなら手間もかからない。