So fügen Sie benutzerdefinierte Layout-Handles programmgesteuert für die Kategorieansicht in Magento 2 hinzu

9

Daher möchte ich ein benutzerdefiniertes Layout-Handle für alle Seiten der Kategorieansicht hinzufügen. Das Handle, das geladen werden soll, hängt von bestimmten Kategorieparametern ab. Daher muss das Handle programmgesteuert mit hinzugefügt werden $page->addPageLayoutHandles()

Scheint einfach ..? Scheinbar nicht

Magento 2 bietet ein nettes Plugin-System, das ich natürlich verwenden wollte. Definieren Sie einfach ein afterExecute()Plugin, das nach der ursprünglichen Kategorie ausgeführt werden soll, execute()und übertragen Sie von dort aus alle Aktualisierungen in das Page-Objekt.

Leider funktioniert dies nicht ganz. Grund dafür ist, dass die ursprüngliche execute()Methode (ganz am Ende) ausgeführt wird. Durch $page->getConfig()->addBodyClass()einen Aufruf dieser Methode wird das Layout automatisch vollständig geladen und generiert, sodass alle nachfolgenden Versuche, neue hinzuzufügen, ausgeführt werden Layout-Handles zu Seite sind völlig nutzlos. Ich habe mich umgesehen, um nicht so elegante Wege zu finden, um dasselbe zu erreichen (immer noch mit Plugins). Ich habe keine gefunden.

Am Ende habe ich meinen eigenen Controller für die Kategorieansicht ausgeführt, aber ich würde es nicht vorziehen, ihn so zu belassen.

Meine Frage lautet also: Wie kann ich (programmgesteuert) neue Seitenlayout-Handles für die Kategorieansicht hinzufügen? und mach es elegant.

Kristjan H.
quelle
Welche Magento-Version verwenden Sie? Denn wo können Sie sehen, dass $page->getConfig()->addBodyClass()Ihr Layout geladen und generiert wird? Ich habe im Moment eine ähnliche Aufgabe, nur mit CMS-Seiten.
Giel Berkers
Ich bin so froh, dass du das bemerkt hast, als du mir eine Menge Kummer erspart hast. Nur zu Ihrer Information: Der Controller für die Kategorieansicht ruft auch $ page-> getConfig () -> addBodyClass () auf, wodurch ein Plugin dafür unbrauchbar wird.
Perry Holden

Antworten:

17

Der XML-Weg

Eine einfache Möglichkeit besteht darin, die folgende Datei in Ihrem Modulordner zu erstellen: view/frontend/layout/catalog_category_view.xmlmit folgendem Inhalt:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="your_custom_handle"/>
</page>

Es ist nicht mehr oder weniger elegant als PHP und nach Ihren Erkenntnissen sicherer.

Der PHP-Weg

Leider scheint es in Ihrem Fall so zu sein, dass PHP die einzige Möglichkeit ist, Handles basierend auf den Parametern der Kategorie dynamisch zu erstellen.

Über Plugins

Anstatt ein Plugin für die execute()Methode Ihrer Aktionsklasse zu erstellen, können Sie auch ein Plugin für die addPageLayoutHandles()Methode von erstellenMagento\Framework\View\Result\Page

Das Hauptproblem besteht darin, dass es bei jedem Aufruf dieser Methode aufgerufen wird und Sie einige Bedingungen in Ihren Plugin-Code einfügen müssen, um sicherzustellen, dass Sie sich auf einer Kategoriesicht befinden.

Über Einstellungen

Eine andere Möglichkeit besteht darin, Einstellungen für die Aktionsklasse "Kategorieansicht" zu verwenden:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Controller\Category\View"
                type="Vendor\Module\Controller\Category\View"/>
</config>

Dann überschreiben Sie in Ihrer benutzerdefinierten Controller-Klasse einfach die execute()Methode, indem Sie die ursprüngliche Methode kopieren / einfügen und Ihre Änderungen direkt in diese Methode einfügen.

Das Hauptproblem besteht darin, dass beim Aktualisieren Ihrer Magento-Installation Änderungen an der ursprünglichen nativen Magento-Aktionsklasse nicht in Ihrer benutzerdefinierten Aktionsklasse berücksichtigt werden.

Raphael beim digitalen Pianismus
quelle
Das Problem ist .. es muss programmatisch hinzugefügt werden. Einfach, weil das zu ladende Handle von den Parametern der Kategorie abhängt.
Kristjan H.
@KristjanH. hmmm ich sehe es ist peinlich, lass mich weiter graben
Raphael bei Digital Pianism
@KristjanH. siehe mein Update
Raphael bei Digital Pianism
1
Mit <präferenz> .. das ist, was ich getan habe, bevor ich die Frage hier geschrieben habe, aber damit bin ich nicht zufrieden. Wie bei der Verwendung eines Plugins für addPageLayoutHandles möchte ich nicht ständig ein Plugin aufrufen, auch wenn die Leistungsbeeinträchtigung nicht vorhanden ist, ist es einfach nicht richtig. Mal sehen, ob hier andere Lösungen erscheinen.
Kristjan H.
Haben Sie danach einen anderen Weg versucht?
LM_Fielding
8

Ich hatte ein ähnliches Problem. Für Kategorien, in denen keine Produktlisten angezeigt werden, benötigte ich ein zusätzliches Handle. Nachdem ich das Handle nicht über das benutzerdefinierte Layout-XML der Kategorie hinzugefügt hatte, fügte ich es schließlich einem Beobachter des layout_load_beforeEreignisses hinzu:

class LayoutLoadBefore implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Framework\Registry
     */
    protected $_registry;

    public function __construct(
        \Magento\Framework\Registry $registry
    )
    {
        $this->_registry = $registry;
    }

    /**
     * add a custom handle to categories of page type 'PAGE'
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return $this
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $action = $observer->getData('full_action_name');
        if ($action != 'catalog_category_view')
            return $this;

        $category = $this->_registry->registry('current_category');
        if (!$category)
            return $this;

        if ($category->getDisplayMode() == $category::DM_PAGE) {
            $layout = $observer->getData('layout');
            $layout->getUpdate()->addHandle('catalog_category_view_cms');
        }

        return $this;
    }
}

Es handelt sich um einen kleinen Leistungseinbruch, da der Beobachter für jeden Seitenaufruf aufgerufen wird. Leider scheinen alle 'category_view'-bezogenen Ereignisse entweder zu früh (Kategorie noch nicht geladen) oder zu spät (Layout bereits verarbeitet) zu sein.

abwechseln
quelle
Vielen Dank! Ich hatte ein ähnliches Problem ( magento.stackexchange.com/questions/156231/… ) und ein Plugin \Magento\Cms\Controller\Page\View::execute()und \Magento\Framework\View\Result\Page::addPageLayoutHandles() or render()habe den Trick nicht gemacht. Diese Lösung der letzten Instanz war die einzige Lösung, die für mich funktioniert hat.
Giel Berkers
1

Versuchen wir, das Ereignis layout_load_before zu beobachten. Die Ausführungsfunktion ist dieselbe wie folgt:

public function execute(\Magento\Framework\Event\Observer $observer)
    {
        if($observer->getFullActionName() == 'catalog_category_view'){
            $observer->getLayout()->getUpdate()->addHandle('your_custom_handles');
        }
    }

Hoffe das wird helfen

Hồ Trung Nghĩa
quelle