Identificadores XML do CMS para atualizações de layout

13

Eu tive alguns cenários em que tentei usar as alças do cms para atualizar o layout de uma página do cms. Por exemplo, eu estava tentando usar o identificador cms_index_index referenciando raiz e definindo o modelo de página. Isso falhou e eu tive que fazer essa atualização de layout através do sistema de administração diretamente nas configurações de exibição da página cms da página inicial.

Eu também tentei adicionar um bloco para fazer referência à esquerda usando o identificador cms_page. Novamente, isso falhou e eu tive que implementar a atualização de layout através do sistema de administração.

Eu li que você não pode atribuir um modelo raiz às páginas do cms. Isso está correto e alguém pode explicar o porquê?

Também me perguntei se havia uma maneira de habilitar os identificadores do cms para usar as referências padrão, como esquerda, direita, raiz, etc.? Parece que sou capaz de referenciar coisas como cabeça e conteúdo muito bem.

Mark Weston
fonte

Respostas:

20

Por que alterar o modelo raiz não funciona

Ambos

Mage_Cms_IndexController::indexAction()

e

Mage_Cms_IndexController::viewAction()

responsáveis ​​por exibir a página inicial padrão e uma página do CMS, respectivamente, chamam um auxiliar:

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

Se você pular para o auxiliar (localizado em app / code / core / Mage / Cms / Helper / Page.php) e seguir renderPage()o método protegido, _renderPage()verá que o Magento está verificando duas vezes o modelo raiz (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);     
}

e

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

Ambas as chamadas acontecem depois que os manipuladores de layout, como "cms_page" e similares, são processados, então você está sem sorte aqui.

O que você pode fazer para alterar o modelo raiz

Há um evento cms_page_renderque você pode usar para adicionar seu próprio identificador de layout XML nas páginas do CMS. Crie sua própria extensão (vou poupar alguns detalhes aqui) e configure o observador de eventos no seu 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>

Adicione seu observador de eventos:

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

Por fim, adicione seu novo identificador XML de layout (por exemplo, no seu 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>

Você também pode usar esse método para adicionar um cms_page_view_afteridentificador ou criar identificadores específicos da página ao cms_page_renderpassar o $pageobjeto ao seu observador.

Por que você não pode adicionar um bloco à "referência esquerda"

Tem certeza de que o modelo que você está usando possui uma coluna esquerda? Essa pergunta pode parecer boba, mas o layout padrão "2 colunas com barra direita", por exemplo, oferece apenas uma área de 'conteúdo' e 'direita'. Posso adicionar blocos à coluna da direita usando cms_pagesem problemas, portanto esse pode ser o problema.

Em geral, você só pode adicionar blocos facilmente a referências e repeti-los se

  • o modelo raiz escolhido usa o bloco que você está referenciando (consulte app/design/frontend/base/default/template/page/*.phtml) e
  • o bloco ao qual você está referenciando é do tipo core/text_list, chama $this->getChildhtml()sem argumentos ou faz outra coisa para ecoar todos os blocos filhos.

Sem mais detalhes, não sei explicar por que seus blocos não ecoam na coluna esquerda ou direita.

Matthias Zeis
fonte
Oi Matthias. Obrigado pela sugestão de adicionar um observador de eventos, vou dar uma olhada em um de nossos desenvolvedores e ver se isso funciona. Esta poderia ser a resposta! O @Alan também fez uma observação semelhante sobre definir o modelo padrão correto para as páginas cms e o fato de as alças serem substituídas. Obrigado pela informação também, acho que já resolvi isso agora.
Mark Weston
Oi. Testei isso e funciona. Também o testei para identificadores específicos de página e está funcionando, mas não é a melhor solução, pois preciso de um identificador para páginas que não serão alteradas. Como teste, usei o identificador da página. $cmsPageId = '_' . str_replace('-', '_', $observer->getEvent()->getPage()->getIdentifier()); Se alguém alterou o URL da página cms, o identificador não funcionará. Idealmente, um campo para 'chave da página' existiria na página do CMS no sistema de administração, então o URL da página, o nome etc poderiam ser alterados e a chave poderia ser a mesma.
Mark Weston
14

Em relação à sua "não é possível adicionar um bloco usando <reference name="left/>, você tem certeza de que sua página do CMS possui um bloco com o nome esquerdo? Por exemplo, se você considerar a página inicial padrão que acompanha os dados de amostra do Magento, ela parece ter um bloco chamado esquerda.

isso é uma coluna da esquerda?

No entanto, se você olhar para a página no back-end, poderá ver que ela está configurada para usar o modelo raiz

`2 columns with right bar`    

e, em seguida, em sua área de conteúdo, a coluna esquerda é adicionada usando a marcação HTML (alterne o WYSIWYG para a visualização de origem)

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

Este gráfico direcionado deixa claro que não há nenhum bloco com o qual leftse conectar ( clique para ver a imagem no tamanho original )

gráfico direcionado gerado com o Commerce Bug

Em relação à configuração de um modelo, se você procurar na fonte o menu suspenso "Layout"

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

Você pode ver quando você está definindo neste campo, o valor real ser salvo é algo como one_column, two_columns_left, etc. Estes valores corespond de alças de layout do mesmo nome.

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

Quando o Magento está renderizando uma página do CMS, ele faz referência aos valores salvos e adiciona o identificador de layout apropriado à página. Embora seja tangencial à pergunta, esse identificador é adicionado aqui

#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);
    }  
    //...
}

Mais importante, porém, é a ordem em que as alças de layout são adicionadas

Alça da guia Bug de comércio

Como você pode ver na captura de tela acima, o page_two_columns_rightidentificador é adicionado após o cms_index_indexidentificador. Isso significa que, se você adicionar o código de atualização xml do layout para alterar o modelo, cms_index_indexseu código será executado, mas o código xml de atualização do layout page_two_columns_rightserá executado depois dele.

Sempre suspeitei que isso ocorra por design, para garantir que o modelo definido na interface do usuário esteja sempre correto. Na versão anterior do Magento, a <action method="setIsHandle"><applied>1</applied></action>chamada de método parece ter existido pelos mesmos motivos.

Portanto, não há como fazer o que você deseja usando o código xml de layout puro. Se você estiver confortável com a criação de módulos personalizados e código de observador, verifique o cms_page_renderevento. Isso é acionado logo antes da loadLayoutUpdateschamada e permite inserir um nome de identificador adicional ou remover os nomes de identificadores existentes.

Alan Storm
fonte
Obrigado Alan, seus comentários sobre a adição de blocos a uma página cms fazem todo o sentido. Normalmente, defino modelos para páginas diferentes usando os vários manipuladores xml que o Magento fornece. Meu entendimento um pouco melhor das páginas cms tornou mais claro o motivo pelo qual tive problemas ao usar referências para páginas cms. Preciso garantir que o identificador padrão em meu page.xml tenha o layout correto para páginas cms. Parece que encobri essa alça, porque geralmente estou exagerando em outro lugar. Isso está correto? Posso perguntar como você produziu o gráfico e qual ferramenta está usando para exibir os identificadores de uma solicitação específica?
Mark Weston
2
@ MarkWeston Os diagramas e interface do usuário são alguns da Commerce Bug, uma ferramenta de depuração comercial que criei e vendi. (consulte alanstorm.com/find_magento_block_name para obter detalhes) Não sei se entendi sua pergunta sobre os identificadores, mas se você estiver definindo um modelo no defaultidentificador, o layout definido no administrador ainda vencerá (ou seja page_two_columns_right, ainda será executado mais tarde). Além disso, Re: terminologia - você não substitui os identificadores, seus identificadores sempre coexistem com os outros - é apenas a ordem em que eles executam afeta o resultado final.
Alan Storm
Felicidades Alan. Entendo o que você quer dizer com chamar o uso de um identificador para definir um modelo que não seja uma substituição - bom ponto. Obrigado pela informação sobre o Commerce Bug.
Mark Weston