RecursiveIteratorIteratorにあるフィルタもしくはイベントのようなもの

RecursiveIteratorIteratorにはフィルターっぽい機能があるようなので試してみた。
RecursiveIteratorをイテレートする際に、子要素にアクセスするところでイベント的に処理が廻ってくる。
RecursiveIteratorIterator::beginChildren
RecursiveIteratorIterator::endChildren
RecursiveIteratorIterator::nextElement

<?php
class riiPrinter extends RecursiveIteratorIterator
{
    public function beginChildren()
    {
        print "<dd>\n<dl>\n";
    }
    public function endChildren()
    {
        print "</dl>\n</dd>\n";
    }
    public function nextElement()
    {
        print " ";
    }
    public function current()
    {
        print $this->_wrapLabel(parent::key()) . $this->_wrapElem(parent::current());
        $this->_printSome();
    }
    protected function _wrapGroup($data)
    {
        return "<div>" . $data ."</div>";
    }
    protected function _wrapElem($data)
    {
        return "<dd>" . $data . "</dd>";
    }
    protected function _wrapLabel($data)
    {
        return "<dt>" . $data . "</dt>";
    }
    protected function _printSome()
    {
        print "<!--" . parent::getDepth() . "-->";
    }
    public function printThis()
    {
        foreach ($this as $data) {
            print $data . "\n";
        }
    }
    public function test()
    {
        return "<dl>\n" . $this->__toString() . "</dl>\n";
    }
    public function __toString()
    {
        ob_start();
        $this->printThis();
        return ob_get_clean();
    }
}

これを使うと

<?php
$target = array(
    'hoge',
    'test1' => array(1,2,3,4,5),
    'test2' => array(11,12,13,14,15),
    'test3' => array(101,102,array('test2' => 'data3'),104,105),
);
$test = new riiPrinter(new RecursiveArrayIterator($target));
echo $test->test();

配列を再帰的にタグに整形して出力できる。
これ、foreachで作ると結構面倒な処理になるんだけど、簡単に再帰処理ができて再利用性も高い。
たとえば、これをベースにして、カテゴリーリストみたいなものを表示するビューヘルパー、もしくはウィジェットを作ってみようかと。

タグのネストについては、仕様を誤解しているかもしれないので、気付いた方はツッコミください。


結果

<dl>
 <dt>0</dt><dd>hoge</dd><!--0-->
<dd>
<dl>
 <dt>0</dt><dd>1</dd><!--1-->
 <dt>1</dt><dd>2</dd><!--1-->
 <dt>2</dt><dd>3</dd><!--1-->
 <dt>3</dt><dd>4</dd><!--1-->
 <dt>4</dt><dd>5</dd><!--1-->
</dl>
</dd>
<dd>
<dl>
 <dt>0</dt><dd>11</dd><!--1-->
 <dt>1</dt><dd>12</dd><!--1-->
 <dt>2</dt><dd>13</dd><!--1-->
 <dt>3</dt><dd>14</dd><!--1-->
 <dt>4</dt><dd>15</dd><!--1-->
</dl>
</dd>
<dd>
<dl>
 <dt>0</dt><dd>101</dd><!--1-->
 <dt>1</dt><dd>102</dd><!--1-->
<dd>
<dl>
 <dt>test2</dt><dd>data3</dd><!--2-->
</dl>
</dd>
 <dt>3</dt><dd>104</dd><!--1-->
 <dt>4</dt><dd>105</dd><!--1-->
</dl>
</dd>
</dl>