3v4l.org

run code in 300+ PHP versions simultaneously
<?php $dbResults = array( array('id' => 1, 'parent_id' => 0, 'link' => '#', 'label' => 'Home'), array('id' => 2, 'parent_id' => 0, 'link' => '#', 'label' => 'Portfolio'), array('id' => 3, 'parent_id' => 0, 'link' => '#', 'label' => 'Projects'), array('id' => 4, 'parent_id' => 2, 'link' => '#', 'label' => 'Design'), array('id' => 5, 'parent_id' => 2, 'link' => '#', 'label' => 'Dev'), array('id' => 6, 'parent_id' => 2, 'link' => '#', 'label' => 'Foo'), array('id' => 7, 'parent_id' => 3, 'link' => '#', 'label' => 'Bar'), ); class Menu { const MENU_CACHE_KEY = 'menu_cache'; /** @var MenuItem[] */ protected $rootNodes = array(); protected $childNodes = array(); /** @var ICache */ protected $cache; /** * @param ICache $cache */ public function setCache(ICache $cache) { $this->cache = $cache; } public function hasCache() { return $this->cache instanceof ICache; } /** * @param MenuItem $menuItem */ public function add(MenuItem $menuItem) { if ($menuItem->isParent()) { $this->addRootNode($menuItem); } else { $this->addChildNode($menuItem); } } /** * @param MenuItem $menuItem */ private function addRootNode(MenuItem $menuItem) { array_push($this->rootNodes, $menuItem); } /** * @param MenuItem $menuItem */ private function addChildNode(MenuItem $menuItem) { $this->ensureChildNodeExists($menuItem->parentId); array_push($this->childNodes[$menuItem->parentId], $menuItem); } /** * @param int $parentId */ private function ensureChildNodeExists($parentId) { if (!isset($this->childNodes[$parentId])) { $this->childNodes[$parentId] = array(); } } /** * @return string */ public function render() { if ($this->hasCache()) { $cached = $this->cache->getItem(self::MENU_CACHE_KEY); if (!empty($cached)) { return $cached; } } $html = '<ul>'; foreach ($this->rootNodes as $menuItem) { $html .= '<li>' . $menuItem->render(); if (!empty($this->childNodes[$menuItem->id])) { $html .= '<ul>'; /** @var $childMenuItem MenuItem */ foreach ($this->childNodes[$menuItem->id] as $childMenuItem) { $html .= '<li>' . $childMenuItem->render() . '</li>'; } $html .= '</ul>'; } $html .= '</li>'; } $html .= '</ul>'; if ($this->hasCache()) { $this->cache->setItem(self::MENU_CACHE_KEY, $html); } return $html; } } class MenuItem { public $id; public $parentId; public $label; public $link; /** * @param array|null $params */ public function __construct($params = null) { if (!is_null($params)) { $this->id = (int) $params['id']; $this->label = $params['label']; $this->link = $params['link']; $this->parentId = (int) $params['parent_id']; } } /** * @return bool */ public function isParent() { return $this->parentId === 0; } /** * @return string */ public function render() { return '<a href="' . $this->link . '">' . $this->label . '</a>'; } } interface ICache { /** * @param string $key * * @return string|null */ public function getItem($key); /** * @param string $key * @param string $value */ public function setItem($key, $value); } $menu = new Menu(); /* $menu->setCache(new RedisCache()); $menu->setCache(new FileCache()); $menu->setCache(new MemcachedCache()); */ foreach ($dbResults as $row) { $menu->add(new MenuItem($row)); } echo $menu->render();
Output for git.master, git.master_jit, rfc.property-hooks
<ul><li><a href="#">Home</a></li><li><a href="#">Portfolio</a><ul><li><a href="#">Design</a></li><li><a href="#">Dev</a></li><li><a href="#">Foo</a></li></ul></li><li><a href="#">Projects</a><ul><li><a href="#">Bar</a></li></ul></li></ul>

This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.

Active branches

Archived branches

Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page


preferences:
42.63 ms | 401 KiB | 8 Q