Добавление ссылок в меню категорий

20

Я знаю, что это старый вопрос с множеством ответов, большинство из них предлагают редактировать шаблон меню, но это не работает для меня. Нет необходимости объяснять, почему, скажем, я немного пристрастен к тому, чтобы делать вещи «правильным» способом.
Этот вопрос может служить материалом для других нуждающихся. Вот оно.
Начиная с Magento 1.7 Верхнее меню строится с помощью события: page_block_html_topmenu_gethtml_before. Это используется Mage_Catalogмодулем для добавления категорий. Я хочу использовать это. Для этого я создал наблюдателя в моем модуле так:

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

В Observer.phpклассе у меня

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

У моего обозревателя есть какой-то другой код, который добавляет все бренды в качестве подпунктов Brandsменю, но здесь в этом нет необходимости.
Это прекрасно работает и добавляет меню Brandsв качестве последнего пункта в меню.
Проблема в том, что я хочу это как первое меню, и мой наблюдатель вызывается после того, как наблюдатель Mage_Catalogдобавляет эти категории. Поскольку нет способа (не то, что я знаю) сортировать порядок наблюдателей на событии ... У меня есть проблема
[РЕДАКТИРОВАТЬ]
Как @Benmarks предположил, что я сделалMage_Catalogмодуль зависит от моего модуля и теперь мой пункт меню является первым в списке. Но я все еще должен добавить меню между категориями и в конце. Создание нового модуля, вероятно, решило бы проблему с элементами в конце меню, но у меня все еще есть проблема с элементами между категориями,
[/ EDIT]
Так что в основном мой вопрос возвращается к « (Как) я могу перемещаться вокруг ребенка? узлы Varien_Data_Tree_Nodeв Varien_Data_Treeобъекте? "
Пожалуйста, не предлагайте добавлять Brandsпервую категорию в дерево категорий. Это не вариант (как я уже сказал ... мой OCD об этих вещах).

Мариус
источник
Есть ли причина не создавать пустые категории и показывать только блок CMS? - Я принимаю «да» в качестве ответа, просто чтобы быть уверенным, что вы думали об этом :)
Фабиан Блехшмидт
1
@FabianBlechschmidt. "Да". Не стоит вдаваться в подробности, но есть причины (некоторые из них могут быть довольно глупыми). Я не делаю "правила" на этом. Так что это должно быть сделано так.
Мариус
@FabianBlechschmidt: Удалять некоторые «туманы» здесь - это веская причина, поэтому вы не скажете, что я упрямый (даже если и я). Пользовательские ссылки (бренды, новые, распродажи и др.) Находятся не в одном месте для всех просмотров магазина. Но все виды магазина используют одни и те же категории. Поэтому я не хочу создавать отдельное дерево для каждого вида магазина. Используя наблюдателя, я могу прочитать некоторые настройки конфигурации и расположить элементы так, как я хочу. Я даже могу добавить пункты меню в зависимости от идентификатора представления магазина.
Мариус
Также интересно, у меня та же проблема, мое решение состоит в том, чтобы переопределить Varien_Data_Tree_Node_Collection и добавить сюда метод сортировки узлов, как я хочу, но я ищу более чистый путь.
Fab

Ответы:

10

После небольшой борьбы вот решение, которое я нашел. Я позволил своему наблюдателю выполнить его после того, как он вошел, Mage_Catalogи решил заново создать меню полностью.
Основная идея состоит в том, чтобы получить все существующие пункты меню, поместить их во временный массив, удалить их из меню, затем добавить мои ссылки между существующими элементами и в конце добавить все элементы в меню снова. Что-то вроде этого:

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

Это похоже на решение моей проблемы, но я надеюсь на более элегантный способ сделать это.

Мариус
источник
Мариус, есть ли другой наблюдатель, кроме page_block_html_topmenu_gethtml_, прежде чем добавлять ссылки в меню категорий?
Прадип Санку
Причина в том, что я использовал того же наблюдателя, но у меня было расширение для мегаменю, которое не вызывает page_block_html_topmenu_gethtml_before.please, дайте мне знать
Pradeep Sanku
@PradeepSanku. Я не знаю других событий. Возможно, расширение, которое вы используете, полностью заменяет главное меню. Вы должны обратиться к разработчику за поддержкой.
Мариус
4

Поскольку нет способа (не то, что я знаю) сортировать порядок наблюдателей по событию ... У меня проблема.

Ах, но есть! В файле объявления вашего модуля установите зависимость от Mage_Catalogвашего модуля, например:

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

Кроме того, вы можете (я думаю) скопировать конфигурацию наблюдателя каталога в область frontendсобытий и деактивировать ее в этой globalобласти. Я предполагаю, что globalсобытия обрабатываются до frontendсобытий. (Я понятия не имею, почему это событие настраивается globalв первую очередь.)

И, конечно, есть и другие варианты, которые вы можете применить через переписывание и PHP.

benmarks
источник
Благодарю. У вас есть мой +1 здесь. Я фактически переместил свое событие внутрь <global>тега, я объявил, Mage_Catalogчто он зависит от моего модуля (даже если я чувствую себя немного «грязным» при этом), и это работает, но в итоге я столкнулся с другой проблемой. Мне нужны другие пункты меню, расположенные между некоторыми категориями и в конце меню, поэтому мне все еще нужно иметь возможность перемещать их по кругу. Я обновлю вопрос.
Мариус
-1
  1. создать новую подкатегорию
  2. изменить ссылку с помощью JavaScript, например, ваша новая категория "75"
jQuery(document).ready(function(){
    document.getElementById("menu75").getElementsByTagName("a")[0].href =

" https: // YourNewLinkink "; });

zatanabee
источник
и как мне узнать идентификатор элемента, если он должен работать с любым идентификатором? Это не жизнеспособное решение. Я не буду называть это даже обходным путем.
Мариус
это работает на моем коде ... :)
zatanabee
id show @ Каталог>
Управление