Bram Antwort hat mir geholfen, hier zu einer Lösung Punkt ist das, was ich brauchte, und wie ich es gelöst (da ich zu ZF2 neu war und Namespaces es dauerte viel länger als es sollte, so hoffentlich wird dies anderen helfen)
Problem
- Wollen
Zend\Navigation
verwenden, um von seiner isActive()
Methode zu profitieren und die in der Übersetzung gebaut, ACL, etc Unterstützung.
- Erforderlich zum Hinzufügen von CSS-Klassennamen zu
<li>
Element und<a>
Element. (ZF2's Menu View Helper unterstützt derzeit einen "entweder oder" -Ansatz)
- Erforderlich, um verschachtelten
<ul>
Elementen CSS-Klassennamen hinzuzufügen.
- benötigt, um zusätzliche Attribute zum
<a>
Element hinzufügen wie data-*="..."
- diese Änderungen benötigt Bootstrap 3 Auszeichnungs
Lösung Beschreibung
- erstellen Kunden View Helfer zu unterstützen, indem sie Verlängerung
Zend\View\Helper\Navigation\Menu
- leicht ändern die
renderNormalMenu()
und htmlify()
Methoden
- Nutzen Sie die Möglichkeit, benutzerdefinierte Eigenschaften zu
Zend\Pages
hinzufügen CSS-Klassen und zusätzliche Attribute zu einigen Elementen
Lösung
hinzufügen Schritt 1
Creat ed benutzerdefinierte Ansicht Helper unter dem Anwendungsmodul src\Application\View\Helper\NewMenu.php
NewMenu.php
<?php
namespace Application\View\Helper;
// I'm extending this class, need to include it
use Zend\View\Helper\Navigation\Menu;
// Include namespaces we're using (from Zend\View\Helper\Navigation\Menu)
use RecursiveIteratorIterator;
use Zend\Navigation\AbstractContainer;
use Zend\Navigation\Page\AbstractPage;
class NewMenu extends Menu
{
// copied fromZend\View\Helper\Navigation\Menu
protected function renderNormalMenu(...){}
// copied from Zend\View\Helper\Navigation\Menu
public function htmlify(...){}
}
Schritt 2
registrierte neue Ansicht Helper mit dem getViewHelperConfig()
in \module\Application\Module.php
<?php
/**
* Zend Framework (http://framework.zend.com/) ...*/
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
// ** snip **
public function getViewHelperConfig() {
return array(
'invokables' => array(
// The 'key' is what is used to call the view helper
'NewMenu' => 'Application\View\Helper\NewMenu',
)
);
}
}
Schritt 3
In meinem Skript layout.phtml
erhalte ich meinen Navigationscontainer und übergebe ihn an den Helfer NewMenu View. Ich habe auch einige Optionen wie Hinzufügen der Eltern <ul>
Klassenname und nicht Etiketten, so dass ich die Standard 'Dropdown-Caret', dass Bootstrap (dh. <b class="caret"></b>
) zu einem Etikett mit einem Dropdown-Menü hinzufügen kann hinzugefügt.
$container = $this->navigation('navigation')->getContainer();
echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false);
Intermission
An dieser Stelle sollten wir mehr oder weniger haben dupliziert nur das Menü Ansicht Helper. Es sollte eine Navigation auf die gleiche Weise wie der Standard View Helper erzeugen.
Schritt 4
In der NewMenu.php
Klasse, entferne ich den $addClassToListItem
Code, um es zu vermeiden, die von den Klassen auf dem falschen Elemente durch Zufall platzieren.
geschützte Funktion renderNormalMenu (...)
// Add CSS class from page to <li>
//if ($addClassToListItem && $page->getClass()) {
// $liClasses[] = $page->getClass();
//}
public function htmlify (...)
// Always apply page class to <a> tag. We'll use a diff. method for <li>
//if ($addClassToListItem === false) {
$attribs['class'] = $page->getClass();
//}
Schritt 5
eine Methode hinzufügen CSS Klassennamen <li>
Tags anzuwenden, da wir die entfernt $addClassTolistItem
Methode. Wir verwenden Sie einfach die Seite Klassen Fähigkeit, benutzerdefinierte Eigenschaften haben und dies tun:
geschützte Funktion renderNormalMenu
// Is page active?
if ($isActive) {
$liClasses[] = 'active';
}
if($wrapClass = $page->get('wrapClass')){
$liClasses[] = $wrapClass;
}
...
nun in unserer Navigation Konfigurationsdatei, können wir einfach eine Eigenschaft hinzufügen wrapClass
namens CSS anwenden Klassen zum Umhüllungselement (<li>
).
config \ autoload \ global.php
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
...
),
...
),
),
...
Schritt 6
Fügen Sie die Fähigkeit, sich auf <a>
wie data-*
zusätzliche Attribute zu haben. Für Bootstrap 3 benötigen Sie zum Beispiel data-toggle="dropdown"
.
public function htmlify (...)
// get attribs for element
$attribs = array(
'id' => $page->getId(),
'title' => $title,
);
// add additional attributes
$attr = $page->get('attribs');
if(is_array($attr)){
$attribs = $attribs + $attr;
}
In Ihrer Konfigurationsdatei, können Sie jetzt eine Eigenschaft mit einer Reihe von zusätzlichen Attribute hinzufügen:
config \ autoload \ global. php
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'attribs' => array(
'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value
),
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
...
),
...
),
),
...
Schritt 7
Fügen Sie die Möglichkeit hinzu, Klassennamen in den Container für geschachtelte Listen einzufügen (d. H. <ul>
).
geschützte Funktion renderNormalMenu()
if ($depth > $prevDepth) {
// start new ul tag
if ($ulClass && $depth == 0) {
$ulClass = ' class="' . $ulClass . '"';
}
// Added ElseIf below
else if($ulClass = $page->get('pagesContainerClass')){
$ulClass = ' class="' . $ulClass . '"';
}
else {
$ulClass = '';
}
$html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
Der ursprüngliche Code im Grunde gesagt, „wenn dies die ersten <ul>
und es gibt eine UL-Klasse ist, fügen Sie es, sonst nichts tun. Also, hat er eine zusätzliche Kontrolle . zu sagen, wenn eine Eigenschaft namens pagesContainerClass
zur Verfügung steht, als auch die Klasse die <ul>
anzuwenden
Dies bedeutet, dass wir die Eigenschaft auf der rechten Seite in unserer Konfiguration hinzufügen müssen:
config \ autoload \ global.php
...
'navigation' => array(
'default' => array(
...
array(
'label' => 'Products <b class="caret"></b>',
'route' => 'products',
'wrapClass' => 'dropdown', // class to <li>
'class' => 'dropdown-toggle', // class to <a> like usual
'attribs' => array(
'data-toggle' => 'dropdown', // Key = Attr name, Value = Attr Value
),
'pages' => array(
array(
'label' => 'Cars',
'route' => 'products/type',
// Give child <ul> a class name
'pagesContainerClass' => 'dropdown-menu',
...
),
...
),
),
...
Wichtig zu beachten, muss die UL-Klasse auf dem ersten Kind Seite eines Kindes gelegt werden, da die bedingte Anweisungen in einem der folgenden Bedingung eingewickelt werden:
if ($depth > $prevDepth) {
// start new ul tag
...
}
Nach dem ersten child wird aufgerufen, $ dept = $ prevDepth und die verschachtelten <ul>
wurden bereits an den Zeichenfolgenpuffer gesendet.
Diese Lösung wurde nicht rigoros getestet, aber die Idee ist, dass einfach nimmt, ist das aktuelle Menü Ansicht Helper, und Überlastungen, die beiden notwendigen Methoden und nur geringfügig geändert, dass.
Ich habe versucht, setPartial()
zu verwenden, aber das nur mit der <li>
Generation geholfen, es immer noch der Menüansicht Helpers' htmlify()
Verfahren wurde mit (von denen alle in Bram Diskussion oben erwähnt wurde).
So jene kleine tweeks auf die Verfahren mit der Herstellung und Verwendung der Fähigkeit der Page-Klasse benutzerdefinierten Eigenschaften zu haben, konnte ich nur einige zusätzliche Logik in den Klassennamen auf den <li>
, <a>
und verschachtelt <ul>
Klassen sowie fügen Sie zusätzliche bekommen Eigenschaften auf den <a>
Elementen, so dass ich meine Zend\Navigation
von der Konfiguration konfigurieren konnte, um im Grunde Bootstrap 3 Navbar Markup ausspucken.
Das Ende-Layout dann sieht genauso aus wie folgt aus:
<nav class="navbar navbar-default navbar-static-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<?php
// Use Zend\Navigation to create the menu
$container = $this->navigation('navigation')->getContainer();
echo $this->NewMenu($container)->setUlClass('nav navbar-nav')->escapeLabels(false);
?>
</div><!-- /.navbar-collapse -->
</nav>
Die Unruhen ich in Betrieb gehalten ein besseres Verständnis von PHP Namespaces war und die entsprechenden Qualified Namespaces in meiner benutzerdefinierten Ansicht Helper, obwohl aufzunehmen benötigt zu haben Ich habe es verlängert.
Das andere Problem war, dass die Navigationsansicht Helper das Menü Ansicht Helper von selbst wie so nennen kann:
$this->navigation('navigation')->menu();
arbeiten Dies wird nicht:
$this->navigation('navigation')->NewMenu();
, weil ich denke, von Namespace-Problemen mit NewMenu
nicht in der Navigation View Helper-Klasse registriert und ich werde es nicht nur dafür erweitern.
Also, hoffentlich wird diese (lange) Antwort anderen helfen, die mit dieser Notwendigkeit kämpfen.
Prost!
Danke für Ihre Antwort. Ja - Ich kann 'data-test' => 'blahblah' hinzufügen und es als $ page-> get ('data-test') abrufen - aber dies hängt es immer noch nicht als Attribut in .. .. Würde ich htmlify dazu überschreiben müssen? –
Ja, Sie müssen den Helper für Menüansichten erweitern und nur die Methode htmlify überschreiben. Schauen Sie sich die htmlify-Methode an und Sie werden ein Array von Attributen sehen. Sie können dort Ihr benutzerdefiniertes Attribut hinzufügen. Siehe meine [Antwort] (http://stackoverflow.com/questions/15017288/injecting-custom-navigation-using-a-view-helper-through-the-servicemanager/15019924#15019924) auf eine andere SO-Frage zur Registrierung Ihre eigenen Navigationshilfen anzeigen. –
Danke für Ihre Antwort. Also - mein Menü hat eigentlich 2 Ebenen in der Tiefe ... Also im Wesentlichen - mit Ansicht teilweise - müsste ich rekursiv über Container iterieren - korrekt? Ich kann nicht einfach nur über Seitenelemente foreach ... –