#layout #magento
#макет #magento
Вопрос:
У меня есть модуль featured products, который я написал, который помещает пользовательский блок на страницу со списком продуктов, соответствующих любому атрибуту (ам), который я определил в блоке. Изначально я заставлял это работать, добавляя {{block...}}
строку в раздел содержимого страницы CMS. Это сработало нормально, но я не получал пейджер. Итак, я исправил это, удалив {{block...}}
строку из раздела содержимого и добавив XML в раздел XML обновления макета следующим образом:
<reference name="content">
<block type="cms/block" name="product_list_top" />
<block type="vps_featured/list" name="vps_featured_list" template="catalog/product/sale_list.phtml">
<block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
<block type="page/html_pager" name="product_list_toolbar_pager"/>
</block>
<action method="setToolbarBlockName"><name>product_list_toolbar</name></action>
<action method="setAttributeName"><name>my_attribute</name></action>
</block>
</reference>
Это также отлично сработало. Затем я решил, что, поскольку существует так много экземпляров этого блока, было бы намного чище, если бы я добавил XML-файл в папку layout для моей темы и поместил туда этот код. Тогда в разделе обновления макета я мог бы просто использовать это вместо:
<reference name="vps_featured_list">
<action method="setAttributeName"><name>other_attribute</name></action>
</reference>
Итак, я создал файл с именем vps_featured.xml
и добавил к нему это:
<layout version="0.1.0">
<default>
<reference name="content">
<block type="cms/block" name="product_list_top" />
<block type="vps_featured/list" name="vps_featured_list" template="catalog/product/sale_list.phtml">
<block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
<block type="page/html_pager" name="product_list_toolbar_pager" />
</block>
<action method="setToolbarBlockName"><name>product_list_toolbar</name></action>
</block>
</reference>
</default>
</layout>
На этот XML-файл обновления макета была ссылка в config.xml
для моего пользовательского модуля featured. Я наивно предполагал, что vps_featured.xml
это будет включено в макет страницы только тогда, когда на странице будет мой VPS Featured block, что произойдет только в этих нескольких случаях на специальных страницах CMS. Очевидно, это не тот случай. Это нарушало работу всех остальных страниц, я думаю, потому что это переопределяло дескриптор по умолчанию.
Итак, это подводит меня к вопросу № 1: Когда XML-файлы макета включаются в макет страницы? Используются ли они для ВСЕХ страниц, независимо от того, действительно ли используется модуль, ссылающийся на них?
Затем я решил попробовать добавить новый дескриптор макета, на который я мог бы ссылаться, когда захочу, на своих страницах CMS. Я изменил свой XML-файл макета, чтобы основная часть находилась внутри <vps_featured_list>
тегов, а не <default>
самих тегов. Это вернуло к жизни другие страницы, но, конечно, мои страницы CMS больше не работали, потому что этот дескриптор обновления макета не используется на этих страницах. Я попытался добавить <update handle="vps_featured_list" />
в раздел XML «Обновление макета» страницы CMS XML, но это не сработало (я этого не ожидал).
Итак, это подводит меня к вопросу № 2: каков правильный способ добиться этого?
Не похоже, что это должно быть так сложно, но, очевидно, я чего-то не понимаю. Я прочитал все, что смог найти о макетах, но это всегда простые примеры, например «добавляйте это на страницу КАЖДОГО продукта». Я не хочу, чтобы что-то добавлялось на КАЖДУЮ страницу cms…лишь некоторые из них. Я застрял в использовании XML-раздела обновления макета для рассматриваемых страниц CMS? Я чувствую, что должен быть более чистый способ.
Спасибо,
Брайан
Ответ №1:
Узел <default/>
— это нечто, называемое «дескриптором макета». Каждый запрос в Magent генерирует несколько таких дескрипторов. Перейдите на вкладку Layout на демонстрационном сайте Commerce Bug Bug demo, чтобы получить представление о типах создаваемых дескрипторов.
Magento объединяет все XML-файлы макета в одно гигантское дерево, называемое макетом пакета. Затем дескрипторы определяют, какие фрагменты обновления XML макета используются для конкретного запроса. Эти фрагменты объединяются в макет страницы. Как вы интуитивно поняли, <default/>
дескриптор всегда добавляется, вот почему вы загружаете каждый сайт в своей системе.
Плохая новость в том, что, хотя для страниц CMS есть дескриптор ( <cms_page_view />
), это все равно будет вопросом «все или ничего». Вы могли бы добавить что-нибудь на все страницы CMS, но не на конкретные страницы CMS. Итак, раздел XML «Обновление макета» администратора CMS — это «правильный» способ сделать то, что вы хотите.
Хорошая новость в том, что вы можете воспользоваться двумя подходами, которые чище того, что вы предлагали до сих пор. Сначала вы можете немного почистить вещи, определив свой собственный дескриптор в вашем XML-файле, а затем использовать специальную команду Layout XML для включения этого дескриптора.
В вашем XML добавьте фрагмент XML для обновления макета внутри пользовательского дескриптора.
<layout version="0.1.0"> <my_fancy_pants_unique_handle_name_which_doesnt_conflict_with_existing_names> <reference name="content"> <block type="cms/block" name="product_list_top" /> <block type="vps_featured/list" name="vps_featured_list" template="catalog/product/sale_list.phtml"> <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml"> <block type="page/html_pager" name="product_list_toolbar_pager" /> </block> <action method="setToolbarBlockName"><name>product_list_toolbar</name></action> </block> </reference> </my_fancy_pants_unique_handle_name_which_doesnt_conflict_with_existing_names> </layout>
Затем в CMS Admin добавьте следующий XML-файл обновления макета для нужных вам страниц
<update handle="my_fancy_pants_unique_handle_name_which_doesnt_conflict_with_existing_names" />
Magento позволяет обновлять XML-фрагменты макета, чтобы добавлять дополнительные дескрипторы к запросу. Это то, что вы делаете выше. Это немного проясняет ситуацию, и если вы хотите изменить что-то в XML, для этого есть централизованное место.
Обновить: Оказывается, что команда <update/> может использоваться только из самих XML-файлов макета. Код, который загружает XML-файл обновления макета для страниц CMS, отличается от кода, который загружает и обрабатывает обновления для файлов XML. Magento буквально добавит что угодно в форму CMS в качестве обновления макета. Он не будет обрабатывать его для рекурсивных обновлений. Итак, добавление чего-то подобного в local.xml
сработало бы
<mock_product_list>
<reference name="head">
<label>Mock Product List</label>
<action method="addItem"><type>skin_js</type><name>js/sw/wall.js</name></action>
</reference>
</mock_product_list>
<cms_page_view>
<update handle="mock_product_list" />
</cms_page_view>
Но вы не можете сделать это напрямую с помощью обновления, применяемого через администратора CMS. Живи и учись.
Все это говорит о том, что подход с виджетами, вероятно, все еще жизнеспособен, и альтернативой вышеупомянутому было бы.
-
Создайте пользовательский модуль с пользовательским классом блоков
-
Класс block не отображает HTML
-
Класс block содержит единственный метод с именем что-то вроде "addFooToLayout"
Затем на вашей странице CMS добавьте обновление, подобное этому
<block type="yourmodule/yourblock" name="unique_name" alias="unique_name">
<action method="addFooToLayout" />
</block>
а затем в вашем определении блока
public addFooToLayout()
{
$layout = Mage::getSingleton('core/layout');
$head = $layout->getBlock('head');
$head->addItem('skin_js','js/sw/wall.js');
//etc...
}
Что-то подобное должно работать и немного понятнее (в зависимости от того, сколько XML-файлов для обновления макета вы хотите добавить). Тем не менее, я не тестировал это, и мое доверие к этому подорвано, поэтому покупатель остерегается.
Второй подход заключается в создании единого виджета, который охватывает то, что вы хотели бы добавить на страницу, а затем с помощью администратора экземпляра виджета добавляет этот виджет в определенные блоки на определенных страницах. Эти ссылки должны помочь вам начать.
Наконец, рискуя показаться зазывалой, я недавно самостоятельно опубликовал книгу о макетах Magento, в которой подробно рассматриваются такого рода проблемы. Это стоит вашего времени, если вы заинтересованы в понимании того, как работает вся система.
Комментарии:
1. Обновлено, чтобы исправить ошибочную информацию о тегах обновления, работающих на страницах CMS.
2. Огромное спасибо @alan-storm за невероятно подробный ответ. Я действительно нашел вашу недавнюю книгу в поисках ответа на этот вопрос и, скорее всего, возьму копию. Интересно, что я попробовал именно то, что вы предложили вначале, что, конечно, не сработало. Скоро я рассмотрю другие ваши предложения. Тем временем XML-файл обновления, похоже, работает просто отлично. Хотя, конечно, хотелось бы обновить дескрипторы для страниц CMS....
3. ОГО!! Я добавил больше, но это заняло слишком много времени и превысило лимит редактирования в 5 минут. Я так устал от всех этих чертовых правил! Я просто хочу быть частью сообщества! Перестаньте заставлять меня проходить через столько бюрократических проволочек!!
4. @BrianVPS Вначале это отстой, но как только вы получите здесь небольшую репутацию, эти проблемы начнут исчезать. Я думаю, что большинство из нас, которые часто используют тег Magento, склонны голосовать за любой вопрос или ответ, который не имеет формы "Halp, это не работает", так что вы моментально станете участником с хорошей репутацией.
5. @BrianVPS: не стесняйтесь покупать книгу Алана. Я только что прочитал это сам и нашел это наиболее интересным и полезным. Много моментов "АГА!" 🙂
Ответ №2:
Тем не менее, этот вопрос уже довольно старый, я нашел его через Google и хотел бы добавить некоторую информацию для тех, кто будет читать этот пост в будущем.
Вчера, когда я прочитал этот вопрос и ответ, а также этот и эту публикации, я стал совершенно уверен, что переопределить / расширить дескриптор макета страницы CMS только для определенных страниц невозможно или довольно сложно. Это привело меня к разработке одного небольшого расширения, которое вставляет любой пользовательский дескриптор макета на любой конкретной странице. Я скоро обновлю этот пост общедоступной ссылкой на расширение.
Но потом я обнаружил, что на самом деле можно просто создать новый шаблон для страницы CMS и назначить этому шаблону любой пользовательский дескриптор макета, см., например, Этот вопрос и ответ от Marius. Вот важная часть этого примера кода:
<global>
<page>
<layouts>
<lookbook module="page" translate="label">
<label>Lookbook</label>
<template>page/1column-lookbook.phtml</template>
<layout_handle>lookbook</layout_handle>
</lookbook>
</layouts>
</page>
</global>
Довольно легко внедрить любой пользовательский дескриптор макета на любую страницу и делать все, что вы хотите, только со страницами, которые используют этот шаблон и ваш пользовательский дескриптор макета. Хотел бы я знать это раньше, надеюсь, этот пост сэкономит чье-то время.