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>