• Willkommen im Zend Framework Forum

    ZF1 Zend Framework 1 + ZF2 Zend Framework 2

    Das Zend Framework Forum ist seit 2006 die erste Anlaufstelle für Zend Framework Entwickler in Deutschland. Mit über 70.000 Beiträgen und einer steigenden Nutzerzahl bietet das Forum hilfreiche Themen und ZF-Tutorials für professionelle Entwickler, fortgeschrittene Programmierer sowie Zend Framework Einsteiger.
    Wenn dies Dein erster Besuch in der Zend Framework Community ist, lies bitte zuerst die Hilfe - FAQ durch. Du musst Dich registrieren, bevor Du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um die Registrierung zu starten. Du kannst auch jetzt schon Beiträge lesen. Hier im Forum findest Du die Zend Framework Hilfe, die Du suchst!

    Grüße an alle Zend Framework Entwickler. Das Team vom Zend Framework Forum!

    Drupal Agentur

Breadcrumb wird nicht angezeigt

Ich habe eine Navigation, die ohne Probleme generiert wird.
PHP:
        $oMenuHelper = $this->navigation('navigation')->menu();
        $oMenuHelper->setUlClass('navmenu');

        echo $oMenuHelper->render();
Leider erhalte ich aber bei Breadcrumbs gar nichts
PHP:
        echo $this->navigation('navigation')
                  ->breadcrumbs()
                  ->setLinkLast(false)
                  ->setMinDepth(0)
                  ->setSeparator(' ≫ ');
Eine Beispiel-Route sieht wie folgt aus:
PHP:
return [
        'router' => [
            'routes' => [
                'home' => [
                    'type' => Segment::class,
                    'options' => [
                        'route'    => '/[:lang]',
                        'defaults' => [
                            'controller' => IndexController::class,
                            'action'     => 'index',
                            'lang'         => 'de',
                        ],
                        'constraints' => [
                            'lang' => '(de)',
                        ],
                    ],
                ],
            ],
        ],
    ];
Die Navigation sieht für die Startseite wie folgt aus:
PHP:
return [
        'navigation' => [
            'default' => [
                'home' => [
                    'type'             => Mvc::class,
                    'order'         => 100,
                    'label'         => 'application_navigation_home',
                    'route'         => 'home',
                    'controller'     => IndexController::class,
                    'action'         => 'index',
                    'resource'        => IndexResource::NAME,
                    'privilege'        => IndexResource::PRIVILEGE_INDEX,
                ],
            ],
        ],
    ];
Wenn ich jetzt Mvc.php (https://github.com/zendframework/zend-navigation/blob/master/src/Page/Mvc.php#L131) durch debugge. Dann ist das $this->routeMatch leer. Deswegen wird die Seite wahrscheinlich auch nicht als Aktiv gesetzt.

Woran kann dies denn liegen? Wo habe ich meinen Fehler?
 

Kaiuwe

Super-Moderator
Woran kann dies denn liegen?
Auf den ersten Blick hätte ich gesagt, dass es am Parameter „lang“ der Route liegt, denn davon weiß die Seite in der Navigation nichts.

Dann ist das $this->routeMatch leer.
Hast du eine eigene Fabrik erstellt, welche den Navigations-Container erstellt?

Nebensache:

Der Code für die Ausgabe von Menü und Breadcrumb geht auch kürzer:
PHP:
<?= $this->navigation('default')->menu()->setUlClass('navmenu') ?>

<?= $this->navigation('default')->breadcrumbs()->setMinDepth(0)->setSeparator(' ≫ ') ?>
Die Navigation sieht für die Startseite wie folgt aus:
PHP:
'controller'     => IndexController::class,
'action'         => 'index',
Wird nicht gebraucht, da du die Route bereits festgelegt hast und diese bereits auf Kontroller und Aktion verweist.
 
Ich habe mich am Beispiel im Buch von Ralf Eggert gehalten. Deswegen verwende ich keine eigene Fabrik für die Navigation. Der Parameter "lang" ist nur der Sprachenschlüssel. Wenn ich diesen aus der Route lösche, dann wird mir trotzdem keine Breadcrumb angezeigt.
 
Ich habe mir jetzt einen Listener erstellt, wo ich mir das manuell überprüfe. Sobald die Reource und Privilege von der aktuellen Seite und von der Navigation übereinstimmen. Setze ich den Parameter $navigation->setActive(true). Dies funktioniert sehr gut.

Bloß habe ich jetzt noch Seiten, wo nicht sichtbar sind. Bei diesen funktioniert es leider nicht. Da diese zum Bearbeiten von Datensätzen vorhanden sind. Diese kann man nicht direkt aufrufen, da ja keine Datensatz-ID in der Navigation bekannt ist. Wie kann ich dies noch hinzufügen, so dass ich hier auch Breadcrumb erhalte?
 

Kaiuwe

Super-Moderator
Deswegen verwende ich keine eigene Fabrik für die Navigation.
Wie sieht deine Konfiguration aus? Gibst du eine Fabrik irgendwo an oder lädst du zend-navigation als Modul?
(Das der „RouteMatch“ fehlt ist falsch und daher die Fragen.)

Der Parameter "lang" ist nur der Sprachenschlüssel.
Nöö, für das ZF ist es ein Parameter. Du verwendest diesen nur als Schlüssel für Sprachen. ;)

Wenn ich diesen aus der Route lösche, dann wird mir trotzdem keine Breadcrumb angezeigt.

Ich habe mir jetzt einen Listener erstellt…
Dies ist nur ein Workaround. Es stimmt aber immer noch etwas nicht in deiner Navigation, denn ein manuelles Setzen ist unnötig.
 
Wie sieht deine Konfiguration aus? Gibst du eine Fabrik irgendwo an oder lädst du zend-navigation als Modul?
(Das der „RouteMatch“ fehlt ist falsch und daher die Fragen.)
Ich lade das Modul Zend\Navigation in der Datei config/application.config.php. Mehr mache ich nicht. Anschließend wurde auch schon die Navigation angezeigt. Bloß nicht die Breadcrumb. Wie kann ich das ändern?
 

Kaiuwe

Super-Moderator
Kannst du mal ein Beispiel bereitstellen, z.B. bei Github? Natürlich komplett reduziert, nur damit man deinen Fehler nachvollziehen kann.
 
Ich habe mal ein sauberes Projekt begonnen. Hier funktioniert es leider.

Deswegen werde ich mal mein großes Projekt überprüfen, wo ich den Fehler eingebaut habe. Bisher habe ich noch nichts gefunden.
 
Wenn ich alle Listener herausgenommen habe, dann wurde auf einmal die Breadcrumb angezeigt. Anschließend bin ich auf die Suche gegangen, wo das Problem lag.

Ich habe einen NavigationListener, wo ich Abgleiche, ob der aktuelle Benutzer, diesen Navigationspunkt überhaupt angezeigt bekommen darf. Wenn nicht, dann wird der Knoten, aus der Navigation entfernt und nicht angezeigt. So habe ich ein flexibleres Berechtigungssystem, als dies mit verschiedenen Rollen aufzubauen.

Soweit ich jetzt herausgefunden habe, liegt es daran, sobald ich in der Factory die Navigation hole, dass dann die Breadcrumb nicht mehr angezeigt wird.

NavigationListenerFactory:
PHP:
/** @var $oNavigation \Zend\Navigation\Navigation */
$oNavigation = $oContainer->get(\Zend\Navigation\Navigation::class);
NavigationListener:
PHP:
public function attach(EventManagerInterface $oEvents, $iPriority = 1)
{
            $this->listeners[] = $oEvents->attach(MvcEvent::EVENT_DISPATCH, [$this, 'prepareNavigation'], -1000);
 }

public function prepareNavigation(MvcEvent $oEvent)
{
            // ....
            $this->_oNavigationHelper->setRole($this->getCurrentRole());
            $this->_oNavigationHelper->setAcl($this->_oUserAcl);
}
Wie kann ich dies anders lösen?
 

Kaiuwe

Super-Moderator
Wenn nicht, dann wird der Knoten, aus der Navigation entfernt und nicht angezeigt. So habe ich ein flexibleres Berechtigungssystem, als dies mit verschiedenen Rollen aufzubauen.
Dies widerspricht sich doch mit deinem Code. Wenn du Seiten entfernst, die nicht vom Benutzer aufgerufen werden sollen, warum setzt du dann noch die Rolle und die ACL in die Navigationshelfer?!
An welcher Stelle ist dieses System flexibler? Und selbst wenn man so vorgehen wollte, dann ergibt es keinen Sinn, die Seiten der Navigation hinzuzufügen, wenn diese kurz danach wieder entfernt werden.
Zusätzlich wird das ganze auch noch während des „Dispatch“-Vorgangs durchgeführt, obwohl noch nicht klar ist, ob überhaupt ein Layout oder View-Skript gerendert wird.

Sehr konfus die Geschichte! :rolleyes:

Soweit ich jetzt herausgefunden habe, liegt es daran, sobald ich in der Factory die Navigation hole, dass dann die Breadcrumb nicht mehr angezeigt wird.
Der „RouteMatch“ ist mit dem „MvcEvent::EVENT_DISPATCH“ vorhanden und daher sollte dies stimmen. Du baust deine Navigation um oder neu, liegt vielleicht hier der Fehler? (den Part sehen wir leider nicht)
 
PHP:
public function prepareNavigation(MvcEvent $oEvent)
        {
            if ($this->_oAuthService->hasIdentity())
            {
                $oPaginator = $this->_oPermissionRepository->getListExtended(1, 9999);

                foreach ($this->_oNavigation AS $mKeyMain => $oValueMain)
                {
                    $sResPriv = $this->getResourcePrivilege($oValueMain->resource, $oValueMain->privilege);

                    /** @var $oEntityPermission \AdminPermission\Model\Entity\PermissionEntity */
                    foreach ($oPaginator->getCurrentItems() As $mKeyPermission => $oEntityPermission)
                    {
                        if ($sResPriv == $oEntityPermission->getTarget()->getZiel())
                        {
                            $iPosition   = $oEntityPermission->getPosition() - 1;
                            $sPermission = substr($this->_oAuthService->getIdentity()->getBerechtigung(), $iPosition, 1);

                            if ($sPermission == 0)
                            {
                                $this->_oNavigation->removePage($oValueMain);
                            }
                        }
                    }
                }
            }
            else
            {
                $this->_oNavigation->removePages();
            }

            $this->_oNavigationHelper->setRole($this->getCurrentRole());
            $this->_oNavigationHelper->setAcl($this->_oUserAcl);
        }
$this->_oPermissionRepository->getListExtended(1, 9999); = Hier erhalte ich die Berechtigungen von der Datenbank!
$sResPriv = Hier bekomme ich dann den String $sResource--$sPrivilege zurück.
 

Kaiuwe

Super-Moderator
Verwirf mal deine Fabrik für den Listener, denn du kannst alles vom „MvcEvent“ holen. Erst den View-Helfer „NavigationHelper::class“ per „ViewHelperManager“ und dann kommst du vom View-Helfer auch an den Container. Ebenfalls bekommst du dein Repository.

Code löschen ist immer schön!
 
Zuletzt bearbeitet:
Verwirf mal deine Fabrik für den Listener, denn du kannst alles vom „MvcEvent“ holen. Erst den View-Helfer „NavigationHelper::class“ per „ViewHelperManager“ und dann kommst du vom View-Helfer auch an den Container. Ebenfalls bekommst du dein Repository.

Code löschen ist immer schön!
Das stimmt! Es wird jetzt die Breadcrumb ausgegeben. Aber warum funktioniert es jetzt? Wenn ich die Klasse von der Fabrik an den Listener übergebe, dann funktioniert es nicht. Warum?
 

Kaiuwe

Super-Moderator
Wenn ich die Klasse von der Fabrik an den Listener übergebe, dann funktioniert es nicht. Warum?
Die Fabrik wird garantiert zu früh aufgerufen und damit steht z.B. kein „RouteMatch“ zur Verfügung. Zum Zeitpunkt der Ausführung vom Listener selber, in deinem Falle „dispatch“, ist der Routing-Vorgang abgearbeitet und „RouteMatch“ vorhanden.

Lass den Listener am „MvcEvent::EVENT_RENDER“ lauschen, denn das reicht aus.
 
Oben