Adicionando links ao menu de categoria

20

Sei que essa é uma pergunta antiga com muitas respostas, a maioria delas sugere editar o modelo de menu, mas isso não funciona para mim. Não há necessidade de explicar por que, digamos, eu sou um pouco viciado em fazer as coisas da maneira "certa".
Esta questão pode servir como material para outras pessoas necessitadas. Aqui vai.
Começando com Magento 1.7 no menu superior é construído usando um evento: page_block_html_topmenu_gethtml_before. Isso é usado pelo Mage_Catalogmódulo para adicionar as categorias. Eu quero usar isso. Para isso, criei um observador no meu módulo como este:

<global>
    <events>
        <page_block_html_topmenu_gethtml_before>
            <observers>
                <my_observer>
                    <class>mymodule/observer</class>
                    <method>addItemsToTopmenuItems</method>
                </my_observer>
            </observers>
        </page_block_html_topmenu_gethtml_before>
    </events>
</global>

Na Observer.phpaula eu tenho

public function addItemsToTopmenuItems($observer){
    //get the menu object: //Type Varien_Data_Tree_Node
    $menu = $observer->getMenu();
    //get the tree object in the menu //type Varien_Data_Tree
    $tree = $menu->getTree();
    //get current page handler
    $action = Mage::app()->getFrontController()->getAction()->getFullActionName();
    $brandNodeId = 'category-node-brand';
    //set the node id, label and url
    $data = array(
        'name' => Mage::helper('catalog')->__('Brands'),
        'id' => $brandNodeId,
        'url' => Mage::getUrl('brands'),
        'is_active' => ($action == 'brands')
    );
    //create a node object
    $brandNode = new Varien_Data_Tree_Node($data, 'id', $tree, $menu);
    //add the node to the menu
    $menu->addChild($brandNode);
    return $this;
}

Meu observador tem algum outro código que adiciona todas as marcas como subitens do Brandsmenu, mas não há necessidade disso aqui.
Isso funciona perfeitamente e adiciona um menu Brandscomo último item no menu.
A questão é que eu quero isso como o primeiro menu e meu observador é chamado após o observador Mage_Catalogque adiciona as categorias. Como não há nenhuma maneira (não que eu saiba) de classificar a ordem dos observadores em um evento ... Eu tenho um problema
[EDIT]
Como o @Benmarks sugeriu, eu fiz oMage_CatalogO módulo depende do meu módulo e agora meu item de menu é o primeiro da lista. Mas ainda tenho que adicionar menus entre as categorias e no final. Criando um novo módulo provavelmente iria resolver o problema com os itens no final do menu, mas ainda tenho um problema com os entre categorias,
[/ EDIT]
Então, basicamente a minha pergunta currículos para " (Como) eu posso me movimentar criança nós de a Varien_Data_Tree_Nodeem um Varien_Data_Treeobjeto? "
Por favor, não sugira adicionar Brandscomo a primeira categoria na árvore de categorias. Esta não é uma opção (como eu disse ... meu TOC sobre essas coisas).

Marius
fonte
Existe um motivo para não criar categorias vazias e mostrar apenas um bloco CMS? - Eu aceito "yes" como resposta, só para ter certeza, você pensou sobre isso :) #
Fabian Blechschmidt
11
@FabianBlechschmidt. "Sim". Não faz sentido entrar em detalhes, mas há motivos (alguns deles podem ser bem estúpidos). Eu não faço as "regras" nesta. Então isso deve ser feito assim.
Marius
@FabianBlechschmidt: Limpar um pouco do "nevoeiro" aqui é uma boa razão para você não dizer que sou teimosa (mesmo que eu seja). Os links personalizados (marcas, novos, vendas e outros) não estão no mesmo local para todas as visualizações da loja. Mas todas as visualizações da loja usam as mesmas categorias. Portanto, não quero criar uma árvore diferente para cada visualização da loja. Ao usar um observador, posso ler algumas definições de configuração e organizar os itens como desejar. Posso até adicionar os itens de menu, dependendo do ID da visualização da loja.
Marius
Também estou interessado, tenho o mesmo problema, minha solução é substituir Varien_Data_Tree_Node_Collection e adicionando aqui um método para classificar nós como eu quero, mas estou procurando uma maneira mais limpa.
Fab

Respostas:

10

Depois de lutar um pouco, aqui está a solução que encontrei. Deixei meu observador executar o que estava lá Mage_Cataloge decidi recriar o menu completamente.
A idéia principal é colocar todos os itens de menu existentes em um array temporário, removê-los do menu e adicionar meus links entre os itens existentes e, no final, adicionar todos os itens ao menu novamente. Algo assim:

public function addItemsToTopmenuItems($observer){
    //get the menu object -Type Varien_Data_Tree_Node
    $menu = $observer->getMenu();
    //get the tree object in the menu -type Varien_Data_Tree
    $tree = $menu->getTree();
    //get current page handler
    $action = Mage::app()->getFrontController()->getAction()->getFullActionName();
    $brandNodeId = 'category-node-brand';
    //set the node id, label and url
    $data = array(
        'name' => Mage::helper('catalog')->__('Brands'),
        'id' => $brandNodeId,
        'url' => Mage::getUrl('brands'),
        'is_active' => ($action == 'brands')
    );
    //create a node object
    $brandNode = new Varien_Data_Tree_Node($data, 'id', $tree, $menu);
    //temporary array with nodes
    $menuItems = array();
    //my first menu item
    $menuItems[] = $brandNode;
    //loop through existing menu items, add them to the array and remove them from the    menu
    foreach ($menu->getChildren() as $child){
        //add the item to the temp array
        $menuItems[] = $child;
        //remove item from the menu
        $menu->removeChild($child);
        //I need to add a new menu item after the category with id 6
        //don't worry the id is not hard coded. it comes from a config setting
        //I just added 6 here to make it easier to read
        if ($child->getId() == 'category-node-6'){
            //create a new node as $brandNode called $newNode
            ...
            //add the node to my temp array
            $menuItems[] = $newNode;
        }
    }
    //add other nodes at the end of my temp array
    ...
    //recreate the menu in the order I need
    foreach ($menuItems as $child){
        $menu->addChild($child);
    }
}

Isso parece resolver o meu problema, mas espero um método mais elegante de fazer isso.

Marius
fonte
Marius existe outro observador que não seja page_block_html_topmenu_gethtml_before para adicionar links ao menu de categorias?
Pradeep Sanku
Razão é que eu tinha usado o mesmo observador, mas eu tinha uma extensão para megamenu que não está chamando page_block_html_topmenu_gethtml_before.please deixe-me saber
Pradeep Sanku
@PradeepSanku. Não conheço nenhum outro evento. Talvez a extensão que você está usando substitua completamente o menu principal. Você deve pedir ao desenvolvedor suporte.
Marius
4

Como não há como (não que eu saiba) classificar a ordem dos observadores em um evento ... Eu tenho um problema.

Ah, mas existe! No arquivo de declaração do módulo, defina a dependência do Mage_Catalogseu módulo, por exemplo:

<modules>
    <Your_Module>
        <active>true</active>
        <codePool>local</codePool>
    </Your_Module>
    <Mage_Catalog>
        <depends>
            <Your_Module/>
        </depends>
    </Mage_Catalog>
</modules>

Além disso, você pode (acho) copiar a configuração do observador de catálogo para a frontendárea de eventos e desativá-la na globalárea. Minha suposição é que os globaleventos são processados ​​antes dos frontendeventos. (Não faço ideia do porquê desse evento estar configurado globalem primeiro lugar.)

E, claro, existem outras opções que você pode efetuar através de reescritas e PHP.

benmarks
fonte
Obrigado. Você tem o meu +1 aqui. Na verdade, mudei meu evento para dentro da <global>tag, declarei Mage_Catalogdepender do meu módulo (mesmo que me sinta um pouco 'sujo') e funciona, mas acabo com outro problema. Eu preciso de alguns outros itens de menu colocados entre algumas categorias e no final do menu, para que eu ainda possa movê-los. Vou atualizar a pergunta.
Marius
-1
  1. criar nova subcategoria
  2. altere o link com javascript, ex. sua nova categoria é "75"
jQuery(document).ready(function(){
    document.getElementById("menu75").getElementsByTagName("a")[0].href =

" https: // YourNewLinkink "; });

zatanabee
fonte
e como sei o id do elemento se ele deve funcionar com qualquer id? Esta não é uma solução viável. Não vou chamá-lo de solução alternativa.
Marius
ele funciona no meu código ... :)
zatanabee
the id show @ Catalog> gerenciar categorias
zatanabee