Como adicionar manipuladores de layout personalizados programaticamente para a exibição de categoria no Magento 2


9

Então, eu quero adicionar um identificador de layout personalizado para todas as páginas de exibição de categoria. O identificador que deve ser carregado depende de certos parâmetros de categoria, portanto, o identificador precisa ser adicionado programaticamente com $page->addPageLayoutHandles()

Parece fácil ..? Aparentemente não

O Magento 2 fornece um bom sistema de afterExecute()plug-ins que eu usaria naturalmente, basta definir um plug-in para ser executado após a categoria original execute()e enviar todas as atualizações para o objeto Page a partir daí.

Infelizmente, não funciona dessa maneira. O motivo é que o execute()método original (no final) será executado $page->getConfig()->addBodyClass()- uma chamada para esse método forçará automaticamente o layout a ser completamente carregado e gerado, portanto, qualquer tentativa subsequente de adicionar novos alças de layout para a página são completamente inúteis. Olhei em volta para encontrar maneiras não tão elegantes de conseguir a mesma coisa (ainda usando plugins) .. não encontrei nenhuma.

Acabei executando meu próprio controlador para exibição de categoria, no entanto, eu não preferiria deixar dessa maneira.

Então, minha pergunta é .. como posso adicionar novos identificadores de layout de página (programaticamente) para exibição de categoria? e faça-o com elegância.


Qual versão do Magento você está usando? Porque onde você pode ver que $page->getConfig()->addBodyClass()carrega e gera seu layout? Estou tendo uma tarefa semelhante no momento, apenas com páginas do CMS.
— Giel Berkers

Estou tão feliz que você tenha notado isso, pois me salvou de muita dor. Apenas para sua informação: o controlador de exibição de categoria também chama $ page-> getConfig () -> addBodyClass (), que torna um plug-in inútil para fazer isso.
— Perry Holden

Respostas:


17

A maneira XML

Bem, uma maneira fácil é criar o seguinte arquivo na pasta do módulo: view/frontend/layout/catalog_category_view.xmlcom o seguinte conteúdo:

<?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>

Não é mais ou menos elegante do que o modo PHP e, de acordo com o que você achou, é mais seguro.

O jeito PHP

Infelizmente, no seu caso, parece que o PHP é a única maneira de conseguir criar dinamicamente identificadores com base nos parâmetros que a categoria possui.

Via plugins

Em vez de criar um plugin no execute()método da sua classe de ação, você pode criar diretamente um plugin no addPageLayoutHandles()método deMagento\Framework\View\Result\Page

O principal problema é que ele será chamado toda vez que esse método for chamado e você terá que adicionar algumas condições no código do plug-in para garantir que você esteja em uma página de visualização por categoria.

Via preferências

Outra maneira de fazer isso seria usar preferências para a classe de ação de exibição de categoria:

<?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>

Em sua classe de controlador personalizado, você simplesmente substitui o execute()método copiando / colando o método original e adicionando suas modificações diretamente nesse método.

O principal problema é que, quando você atualizar sua instalação do Magento, se forem adicionadas alterações à classe de ação original do Magento, ela não será refletida na sua classe de ação personalizada.


O problema é .. ele precisa ser adicionado programaticamente. Simplesmente porque o identificador que está sendo carregado depende dos parâmetros que a categoria possui.
— precisa

@KristjanH. hmmm eu ver que é embaraçoso, deixe-me cavar ainda mais
— Raphael em Digital pianismo

@KristjanH. veja minha atualização
— Raphael no Digital Pianism

11
Usando <preference> .. ou seja, o que fiz antes de escrever a pergunta aqui, no entanto, não estou feliz com isso. Mesmo com o uso de um plug-in no addPageLayoutHandles, não quero chamar um plug-in o tempo todo, mesmo que a penalidade de desempenho seja inexistente, isso não é correto. Vamos ver se outras soluções aparecem aqui.
— precisa

Você tentou outra maneira depois disso?
— LM_Fielding 12/12

8

Eu tive um problema parecido. para categorias que não mostram listagens de produtos, eu precisava de uma alça extra. depois de não adicionar o identificador através do XML de layout personalizado da categoria, acabei adicionando-o em um observador no layout_load_beforeevento:

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;
    }
}

há um pequeno impacto no desempenho envolvido, pois o observador é chamado para todas as visualizações de página. infelizmente, todos os eventos relacionados a 'category_view' parecem muito cedo (categoria ainda não carregada) ou muito tarde (layout já processado).


Obrigado! Eu tive um problema semelhante ( magento.stackexchange.com/questions/156231/… ) e um plug-in ativado\Magento\Cms\Controller\Page\View::execute() e \Magento\Framework\View\Result\Page::addPageLayoutHandles() or render()não funcionou. Essa solução de último recurso foi a única solução que funcionou para mim.
— Giel Berkers

1

Vamos tentar observar o evento layout_load_before. A função de execução será a mesma:

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

Espero que isso ajude

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.