CMS XML Handles для обновлений макета

13

У меня было несколько сценариев, в которых я пытался использовать дескрипторы cms для обновления макета страницы cms. Например, я пытался использовать дескриптор cms_index_index, ссылающийся на корневой каталог и настраивая шаблон страницы. Это не удалось, и мне пришлось сделать это обновление макета через систему администратора непосредственно в настройках отображения страницы cms на домашней странице.

Я также попытался добавить блок к ссылке слева, используя дескриптор cms_page. Снова это не удалось, и мне пришлось реализовать обновление макета через систему администратора.

Я читал, что вы не можете назначить корневой шаблон для страниц CMS. Это правильно, и кто-нибудь может объяснить, почему?

Мне также было интересно, есть ли способ, позволяющий ручкам cms использовать стандартные ссылки, такие как left, right, root и т. Д.? Кажется, я могу просто ссылаться на такие вещи, как голова и контент.

Марк Уэстон
источник

Ответы:

20

Почему смена корневого шаблона не работает

И то и другое

Mage_Cms_IndexController::indexAction()

и

Mage_Cms_IndexController::viewAction()

которые отвечают за отображение домашней страницы по умолчанию и страницы CMS, соответственно, вызывают помощника:

Mage::helper('cms/page')->renderPage($this, $pageId)

Если вы перейдете к помощнику (расположенному в app / code / core / Mage / Cms / Helper / Page.php) и перейдете renderPage()к защищенному методу, _renderPage()вы увидите, что Magento дважды проверяет корневой шаблон (Magento CE 1.7. 0.2):

if ($page->getRootTemplate()) {
    $handle = ($page->getCustomRootTemplate()
                && $page->getCustomRootTemplate() != 'empty'
                && $inRange) ? $page->getCustomRootTemplate() : $page->getRootTemplate();
    $action->getLayout()->helper('page/layout')->applyHandle($handle);     
}

и

if ($page->getRootTemplate()) {
    $action->getLayout()->helper('page/layout')
        ->applyTemplate($page->getRootTemplate());
}

Оба вызова происходят после того, как обрабатываются дескрипторы макета, такие как "cms_page" и тому подобное, так что вам не повезло.

Что вы можете сделать, чтобы изменить корневой шаблон

Существует событие, cms_page_renderкоторое вы можете использовать для добавления собственного дескриптора макета XML на страницах CMS. Создайте свое собственное расширение (я сэкономлю некоторые детали здесь) и настройте наблюдатель событий в вашем config.xml:

<?xml version="1.0"?>
<config>
    <modules>
        <Emzee_Cms>
            <version>0.0.1</version>
        </Emzee_Cms>
    </modules>

    <global>
        <events>
            <cms_page_render>
                <observers>
                    <emzee_cms_page_render>
                        <class>emzee_cms/observer</class>
                        <method>cms_page_render</method>
                    </emzee_cms_page_render>
                </observers>
            </cms_page_render>
        </events>
        <models>
            <emzee_cms>
                <class>Emzee_Cms_Model</class>
            </emzee_cms>
        </models>
    </global>
</config>

Добавьте свой наблюдатель события:

<?php

class Emzee_Cms_Model_Observer
{
    public function cms_page_render(Varien_Event_Observer $observer)
    {
        $action = $observer->getEvent()->getControllerAction();

        $actionName = strtolower($action->getFullActionName());
        $action->getLayout()->getUpdate()
            ->addHandle($actionName . '_after');
        return $this;
    }
}

Наконец, добавьте свой новый XML-дескриптор макета (например, в свой local.xml):

<?xml version="1.0"?>
<layout version="0.1.0">
    <cms_index_index_after>
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
    </cms_index_index_after>
</layout>

Вы также можете использовать этот метод для добавления cms_page_view_afterдескриптора или создания специфических для страницы дескрипторов при cms_page_renderпередаче $pageобъекта вашему наблюдателю.

Почему вы не можете добавить блок в «ссылку слева»

Вы уверены, что шаблон, который вы используете, имеет левый столбец? Этот вопрос может показаться глупым, но по умолчанию макет «2 столбца с правой полосой», например, предлагает только «контент» и «правую» область. Я могу добавить блоки в правый столбец, используя cms_pageбез проблем, так что это может быть проблемой.

В общем, вы можете легко добавлять блоки в ссылки и отображать их, если

  • выбранный корневой шаблон использует блок, на который вы ссылаетесь (см. app/design/frontend/base/default/template/page/*.phtml) и
  • блок, на который вы ссылаетесь, имеет тип core/text_list, вызывает $this->getChildhtml()без аргументов или делает что-то еще, чтобы повторить все дочерние блоки.

Без дальнейших подробностей я не могу сказать вам, почему ваши блоки не отображаются в левой или правой колонке.

Матиас Цейс
источник
Привет Матиас. Спасибо за предложение добавить наблюдателя событий, я посмотрю с одним из наших разработчиков и посмотрим, получится ли это. Это может быть ответом! @Alan также указал на то, что правильный набор шаблонов по умолчанию для страниц cms установлен, а также что переопределены дескрипторы. Спасибо за информацию, я думаю, я понял, что понял.
Марк Уэстон
Здравствуй. Проверено это, и это работает. Также проверил его на специфичные для страницы дескрипторы, и он работает, но это не самое удачное решение, так как мне нужен идентификатор для страниц, которые нельзя изменить. В качестве теста я использовал идентификатор страницы. $cmsPageId = '_' . str_replace('-', '_', $observer->getEvent()->getPage()->getIdentifier()); Если кто-то изменил URL-адрес страницы cms, дескриптор не будет работать. В идеале поле для «ключа страницы» должно существовать на странице CMS в системе администратора, тогда URL-адрес страницы, имя и т. Д. Можно изменить, а ключ можно оставить прежним.
Марк Уэстон
14

Относительно того, что вы «не можете добавить блок с помощью <reference name="left/>, вы уверены, что на вашей странице CMS есть блок с именем left? Например, если вы рассматриваете домашнюю страницу по умолчанию, которая поставляется с образцами данных Magento, она, кажется, имеет блок с именем осталось.

это левый столбец?

Однако, если вы посмотрите на страницу в серверной части, вы увидите, что она настроена на использование корневого шаблона.

`2 columns with right bar`    

и затем в его области содержимого, левый столбец добавляется с использованием разметки HTML (переключение WYSIWYG в исходное представление)

<div class="col-left side-col">
<p class="home-callout"><a href="{{store direct_url="apparel/shoes/womens/anashria-womens-premier-leather-sandal.html"}}"><img src="{{skin url='images/ph_callout_left_top.gif'}}" alt="" border="0" /></a></p>
<p class="home-callout"><img src="{{skin url='images/ph_callout_left_rebel.jpg'}}" alt="" border="0" /></p>
{{block type="tag/popular" template="tag/popular.phtml"}}</div>

Этот ориентированный график дает понять, что в названии нет блока, leftк которому можно подключиться ( щелкните для полноразмерного изображения )

ориентированный граф, созданный с помощью Commerce Bug

Что касается настройки шаблона, если вы посмотрите на источник для «Макет» выпадающего

<select id="page_root_template" name="root_template" class=" required-entry select">
    <option value="empty">Empty</option>
    <option value="one_column">1 column</option>
    <option value="two_columns_left">2 columns with left bar</option>
    <option value="two_columns_right" selected="selected">2 columns with right bar</option>
    <option value="three_columns">3 columns</option>
</select>

Когда вы устанавливаете это поле, вы можете увидеть, что фактическое значение сохраняется как-то так one_column, two_columns_leftи т. Д. Эти значения основываются на дескрипторах макета с тем же именем.

#File: app/design/frontend/default/modern/layout/page.xml
<page_one_column translate="label">
    <label>All One-Column Layout Pages</label>
    <reference name="root">
        <action method="setTemplate"><template>page/1column.phtml</template></action>
        <!-- Mark root page block that template is applied -->
        <action method="setIsHandle"><applied>1</applied></action>
        <action method="setLayoutCode"><name>one_column</name></action>
    </reference>
</page_one_column>
...
<page_two_columns_left translate="label">
    <label>All Two-Column Layout Pages (Left Column)</label>
    <reference name="root">
        <action method="setTemplate"><template>page/2columns-left.phtml</template></action>
        <!-- Mark root page block that template is applied -->
        <action method="setIsHandle"><applied>1</applied></action>
        <action method="setLayoutCode"><name>two_columns_left</name></action>
    </reference>
</page_two_columns_left>

Когда Magento отображает страницу CMS, она ссылается на сохраненные значения и добавляет соответствующий дескриптор макета на страницу. Хотя это касается вопроса, этот дескриптор добавлен здесь

#File: app/code/core/Mage/Cms/Helper/Page.php
protected function _renderPage(Mage_Core_Controller_Varien_Action  $action, $pageId = null, $renderLayout = true)
{
    //...
    $action->addActionLayoutHandles();        
    if ($page->getRootTemplate()) {
        $handle = ($page->getCustomRootTemplate()
                    && $page->getCustomRootTemplate() != 'empty'
                    && $inRange) ? $page->getCustomRootTemplate() : $page->getRootTemplate();
        $action->getLayout()->helper('page/layout')->applyHandle($handle);
    }  
    //...
}

Более важно, хотя это порядок, в котором маркеры макета добавляются в

Обрабатывает вкладку Commerce Bug

Как вы можете видеть на скриншоте выше, то page_two_columns_rightручка добавляется после того, как на cms_index_indexручке. Это означает, что если вы добавите код обновления макета XML, чтобы изменить шаблон в cms_index_indexвашем коде, он запустится, но page_two_columns_rightпосле него будет запущен код обновления макета XML .

Я всегда подозревал, что это сделано для того, чтобы шаблон, заданный в пользовательском интерфейсе, всегда был правильным. В предыдущей версии Magento <action method="setIsHandle"><applied>1</applied></action>вызов метода, по-видимому, существовал по тем же причинам.

Таким образом, нет никакого способа сделать то, что вы хотите, используя чистый XML-код макета. Если вам удобно создавать собственные модули и код наблюдателя, посмотрите на cms_page_renderсобытие. Это срабатывает непосредственно перед loadLayoutUpdatesвызовом и позволит вам вставить дополнительное имя дескриптора или удалить существующие имена дескрипторов.

Алан Сторм
источник
Спасибо, Алан, ваши комментарии относительно добавления блоков на страницу cms имеют полный смысл. Я обычно устанавливаю шаблоны для разных страниц, используя различные маркеры xml, которые предоставляет Magento. Мое немного лучшее понимание страниц cms сделало более понятным, почему у меня были проблемы с использованием ссылок на страницы cms. Мне нужно убедиться, что дескриптор по умолчанию в моем page.xml имеет правильный макет для страниц CMS. Кажется, я замаскировал эту ручку, потому что я обычно переоцениваю ее в другом месте. Это верно? Могу я спросить, как вы создали график и какой инструмент вы используете для просмотра маркеров для конкретного запроса?
Марк Уэстон
2
@MarkWeston Диаграммы и пользовательский интерфейс, некоторые из Commerce Bug, коммерческого инструмента отладки, который я создал и продал. (см. подробности на alanstorm.com/find_magento_block_name ) Я не уверен, что понял ваш вопрос об дескрипторах, но если вы устанавливаете шаблон в defaultдескрипторе, то макет, заданный в админке, все равно победит (т.е. page_two_columns_rightвсе равно будет работать потом). Кроме того, терминология Re: вы не переопределяете дескрипторы, ваши дескрипторы всегда сосуществуют с остальными - их порядок влияет на конечный результат.
Алан Сторм
Ура алана. Я понимаю, что вы имеете в виду, когда называете использование дескриптора, чтобы шаблон не был переопределением - хороший момент. Спасибо за информацию о Commerce Bug.
Марк Уэстон