PHP: Дерево меню из объектов

Предлагаю необычный способ построения дерева меню из объектов любой степени вложенности, используя преимущества php5 и вызов методов цепочкой

В первую очередь опишем класс - представляющий собой 1 элемент меню:

class MenuItem {
public $name = '';
public $caption = '';
public $sub = array();
public static function factory($name, $caption) {
return new MenuItem($name, $caption);
}
public function __construct($name, $caption) {
$this->name = $name;
$this->caption = $caption;
}
public function & addSub(MenuItem &$item) {
$this->sub[] = $item;
return $this;
}
public function __toString($base_prefix = NULL) {
$txt = '';
$prefix = is_null($base_prefix) ? url::site() . 'moder' : $base_prefix;
if (!is_null($prefix)) $txt .= "<li>";
$txt .= "<a href='{$prefix}{$this->name}'>{$this->caption}</a>\n";
if (count($this->sub)) {
$txt .= "<ul>";
foreach($this->sub as $s)
$txt .= $s->__toString("{$prefix}{$this->name}/");
$txt .= "</ul>\n";
}
if (!is_null($prefix)) $txt .= "</li>";
return $txt;
}
}

Меню на объектахДумаю понятно, что вся фишка не в перегруженном методе __toString(который больше всего строк :D - это всего лишь view-часть), а в статическом методе factory который возвращает экземпляр объекта меню, и самое главное, в addSub - добавляющий подменю и возвращающий ссылку на этот же объект, в котором был добавлен элемент.

Разумется, в __toString может быть всё что угодно, зависит от вашей фантазии. Создание разметки внутри (фактически) логики - это нарушение MVC, зато хорошо наглядно. Данную штуку я использовал вместе с фреймворком kohana, котороую имел глупость честь использовать в новом проекте.

Пример кода "в одну строчку", который строит меню на картинке:

echo MenuItem::factory('', 'Начало')
->addSub(MenuItem::factory('torrents', 'Торренты')
->addSub(MenuItem::factory('index', 'Статистика'))
->addSub(MenuItem::factory('unchecked', 'Непроверенные'))
->addSub(MenuItem::factory('active', 'Активные'))
->addSub(MenuItem::factory('finished', 'Завершённые'))
->addSub(MenuItem::factory('monitor', 'Монитор')) )
->addSub(MenuItem::factory('users', 'Пользователи')
->addSub(MenuItem::factory('index', 'Статистика'))
->addSub(MenuItem::factory('unchecked', 'Непроверенные'))
->addSub(MenuItem::factory('recent', 'Новые'))
->addSub(MenuItem::factory('online', 'Online')) )
->addSub(MenuItem::factory('movies', 'Фильмы')
->addSub(MenuItem::factory('genres', 'Жанры'))
->addSub(MenuItem::factory('unchecked', 'Непровереные'))
->addSub(MenuItem::factory('manage', 'Управление')) );

Думаю, этот подход можно вынести во многие вещи.


Навеянно фреймворком kohana.
Который поочерёдно вызывет то ненависть,
то благодарность - странный он какой то.