ZF2 Navigation Menu con integrazione di Twitter Bootstrap
1 Gen

Out Of Date Warning
Questo post è stato pubblicato più di 2 anni fa (il 1 Gennaio 2014). Le idee vanno avanti velocemente, le prospettive cambiano quindi i contenuti potrebbero non essere aggiornati. Ti prego di tenere in considerazione questo, e di verificare le informazioni tecniche presenti nell'articolo prima di farne affidamento per i tuoi scopi.Dato che Twitter Boostrap (v3) è il front-end framework più utlizzato, nonchè quello “installato” di default con la ZendSkeletonApplication vediamo come aggiornare il Navigation Menu Helper affinchè si adatti alla Navbar di Boostrap.
Problema
Il problema principale è che di default il navigation menu helper rende, logicamente, un menù con sintassi neutra:
1 2 3 4 5 6 7 8 9 10 |
<ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> </li> <li> <a href="/products/studio">Foo Studio</a> </li> </ul> |
E fin qui tutto bene. Tuttavia in caso di sotto menù renderà qualcosa tipo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<ul class="navigation"> <li class="active"> <a href="/products/server">Foo Server</a> <ul> <li class="active"> <a href="/products/server/faq">FAQ</a> </li> <li> <a href="/products/server/editions">Editions</a> </li> <li> <a href="/products/server/requirements">System Requirements</a> </li> </ul> </li> </ul> |
che male si adatta alla Navbar di Boostrap.
Soluzione
Una soluzione sarebbe quella di rendere un menù ad unica profondità:
1 2 3 4 5 6 7 |
<?php echo $this->navigation('my_navigation') ->menu() ->setUlClass('nav navbar-nav') ->setMaxDepth(0) ->setRenderInvisible(false)?> |
Tuttavia in questo modo non risolviamo il problema ma lo bypassiamo.
La soluzione migliore sarebbe quella si utilizzare i partials per rendere il menù all’interno di un nostro template.
Il nostro partial potrebbe essere qualcosa di simile a questo:
application/navigation/mynav.phtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<ul class="<?= $this->navigation()->menu()->getUlClass() ?>"> <?php foreach ($this->container as $page): ?> <?php if (!$page->isVisible() || !$this->navigation()->accept($page)) continue; ?> <?php $hasChildren = $page->hasPages() ?> <?php if (!$hasChildren): ?> <li<?php if ($page->isActive()) echo ' class="active"'; ?>> <a href="<?php echo $page->getHref() ?>"> <?php if (null !== $page->get("icon")): ?> <i class="<?php echo $page->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($page->getLabel()) ?> </a> </li> <?php else: ?> <li class="dropdown<?php if ($page->isActive()) echo ' active'; ?>"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <?php if (null !== $page->get("icon")): ?> <i class="<?php echo $page->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($page->getLabel()) ?> <b class="caret"></b> </a> <ul class="dropdown-menu"> <?php foreach ($page->getPages() as $child): ?> <?php if (!$child->isVisible() || !$this->navigation()->accept($child)) continue; ?> <li<?php if ($child->isActive()) echo ' class="active"'; ?>> <a href="<?php echo $child->getHref() ?>"> <?php if (null !== $child->get("icon")): ?> <i class="<?php echo $child->get("icon"); ?>"></i> <?php endif; ?> <?= $this->translate($child->getLabel()) ?> </a> </li> <?php endforeach ?> </ul> </li> <?php endif ?> <?php endforeach ?> </ul> |
A questo punto possiamo usare la Navigation factory di default (\Zend\Navigation\Service\DefaultNavigationFactory
) oppure crearcene una propria:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
namespace Application\Navigation\Service; use Zend\Navigation\Service\DefaultNavigationFactory; class MyNavigationFactory extends DefaultNavigationFactory { protected function getName() { return 'mynav'; } } |
Quindi in un config file:
1 2 3 4 5 6 7 8 9 |
return array( 'service_manager' => array( 'factories' => array( 'my_navigation' => 'Application\Navigation\Service\MyNavigationFactory', ), ), ); |
Nella layout view:
1 2 3 4 5 6 7 8 |
<?php echo $this->navigation('my_navigation') ->menu() ->setUlClass('nav navbar-nav') ->setMaxDepth(1) ->setPartial(array('partial/mynav.phtml', 'Application')) ?> |
Esempio utlizzo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
'navigation' => array( 'admin' => array( 'mynav' => array( 'label' => 'Home', 'route' => 'home', 'order' => -1, 'icon' => 'glyphicon glyphicon-home', 'pages' => array( array( 'label' => 'Page1', 'route' => 'application/page1', ), array( 'label' => 'Page2', 'uri' => '/application/page2', ), array( 'label' => 'Page3', 'route' => '/application/page3', ), ), ), ), ), |
Conclusioni
Da tenere presente che così com’è scritto il partial tiene in considerazione un solo livello di profondità.
Inoltre al fine di supportare il caret in caso di menù con sottolivelli e le icone sulle voci del menù l’helper è venuto piuttosto “laborioso”.
Se avessimo rinunciato a questi avremmo potuto utilizzare il metodo htmlify()
del Zend\View\Helper\Navigation\Menu
che avrebbe reso il codice un po’ più snello.
Il metodo ritorna una stringa contenente un elemento ‘a’ per la pagina data se l’href non è vuoto, ed un elemento ‘span’ se questo è vuoto.
1 2 3 |
<?php echo $this->navigation()->menu()->htmlify($page) . PHP_EOL; ?> |
Github
https://github.com/simogrima/Zf2-TwitterBoostrap-NavigationMenu
Risorse
http://framework.zend.com/manual/2.1/en/modules/zend.navigation.view.helper.menu.html
http://stackoverflow.com/questions/14884572/zend-framework-2-navigation-menu-twitter-bootstrap-integration