使用 CMS 页面进行布局更新的正确方法是什么?

发布于 2024-11-03 17:12:18 字数 2909 浏览 0 评论 0原文

我编写了一个特色产品模块,该模块在页面上放置了一个自定义块,其中包含与我在块中定义的任何属性相匹配的产品列表。最初,我通过向 CMS 页面的内容部分添加 {{block...}} 行来使其工作。这工作得很好,但我没有得到寻呼机。因此,我通过从内容部分删除 {{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 文件添加到我的主题的布局文件夹中并将此代码放入其中,则会更加清晰。然后,在“布局更新”部分中,我可以简单地使用以下内容:

<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 用于我的自定义特色模块。我天真地认为,只有当我的 VPS 精选块位于页面上时,vps_featured.xml 才会合并到页面布局中,而这种情况只会发生在特殊 CMS 页面上的少数实例中。显然事实并非如此。我猜这破坏了所有其他页面,因为它覆盖了默认句柄。

因此,这引出了问题 #1:布局 xml 文件何时包含在页面布局中?它们是否用于所有页面,无论引用它们的模块是否实际使用?

然后,我决定尝试添加一个新的布局句柄,当我需要在 CMS 页面中引用时,我可以引用该句柄。我修改了布局 XML 文件,因此主要部分位于 标记内,而不是 标记内。这使其他页面恢复了生机,但当然,我的 CMS 页面不再工作,因为这些页面上没有使用布局更新句柄。我尝试将 添加到 CMS 页面的布局更新 XML 部分,但这不起作用(我没想到它会起作用)。

因此,这让我想到了问题#2:完成此操作的正确方法是什么?

这听起来并不应该如此困难,但显然我错过了一些东西。我已经阅读了我能在布局上找到的所有内容,但它们总是简单的示例,例如“将其添加到每个产品页面”。我不想在每个 cms 页面上添加一些内容...只是其中的几个。我是否在使用相关 CMS 页面的布局更新 XML 部分时遇到困难?我觉得必须有一种更清洁的方法。

谢谢,

布莱恩

I have a featured products module I wrote that puts a custom block on the page with a list of products that match whatever attribute(s) I've defined in the block. Originally I had it working by adding a {{block...}} line to the Content section of the CMS page. This worked fine, but I wasn't getting the pager. So, I fixed that by removing the {{block...}} line from the Content section and adding XML to the Layout Update XML section like so:

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

This also worked great. I then decided, since there are so many instances of this block, that it would be much cleaner if I added an XML file to the layout folder for my theme and put this code in there. Then, in the Layout Update section, I could simply have this instead:

<reference name="vps_featured_list">
    <action method="setAttributeName"><name>other_attribute</name></action>
</reference>

So, I created a file called vps_featured.xml and added this to it:

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

This layout update XML file was referenced in the config.xml for my custom featured module. I naively assumed that vps_featured.xml would only get incorporated into the page layout when my VPS Featured block was on the page, which would only happen in these few instances on special CMS pages. Apparently that is not the case. This broke every other page, I guess because it was overriding the default handle.

So this leads me to question #1: When are the layout xml files included in the page layout? Are they used for ALL pages, regardless of whether or not the module referencing them is actually used?

I then decided to try adding a new layout handle that I could reference when I want in my CMS pages. I modified my layout XML file so the main part is within <vps_featured_list> tags rather than the <default> tags. This brought the other pages back to life, but of course, my CMS pages no longer worked because that layout update handle isn't being used on those pages. I tried adding <update handle="vps_featured_list" /> to the Layout Update XML section of the CMS page, but that didn't work (I didn't expect it to).

So this brings me to question #2: What's the correct way to accomplish this?

This doesn't sound like it should be this difficult, but clearly I'm missing something. I've read all I can find on layouts but they are always simple examples, like "add this to EVERY product page". I don't want something added to EVERY cms page...just a few of them. Am I stuck using the Layout Update XML section for the CMS pages in question? I feel like there has to be a cleaner way.

Thanks,

Brian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

看海 2024-11-10 17:12:18

节点 称为“布局句柄”。每个对 Magent 的请求都会生成许多这样的句柄。查看Commerce Bug 演示网站上的布局选项卡,了解生成的句柄类型。

Magento 将所有布局 XML 文件合并到一棵称为包布局的巨型树中。然后,句柄确定哪些布局 XML 更新片段用于特定请求。这些片段被组合到页面布局中。正如您的直觉, 句柄是始终 添加的,这就是为什么您要屏蔽系统中的每个站点。

坏消息是,虽然有 CMS 页面的句柄 (),但它仍然是一件要么全有要么全无的事情。您可以向所有 CMS 页面添加内容,但不能向特定CMS 页面添加内容。所以,是的,CMS 管理的布局更新 XML 部分是执行您想要的操作的“正确”方法。

好消息是,您可以采取两种比您迄今为止提出的更干净的方法。 首先,您可以通过在 XML 文件中定义自己的句柄来清理一些内容,然后使用特殊的布局 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 管理中,为您想要的页面添加以下布局更新 XML

<update handle="my_fancy_pants_unique_handle_name_which_doesnt_conflict_with_existing_names" />

Magento 允许布局更新 XML 片段向请求添加额外的句柄。这就是你上面所做的。这使事情变得简单一些,如果您想更改某些 XML,可以在一个集中的位置进行更改。

更新:事实证明,命令只能在布局 XML 文件本身中使用。加载 CMS 页面的布局更新 XML 的代码与加载和处理 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 管理员应用更新来执行此操作。生活和学习。

尽管如此,小部件方法可能仍然可行,并且可以作为上述方法的替代方案。

  1. 使用自定义块类创建自定义模块

    使用

  2. 块类不呈现 HTML

  3. 块类包含一个名为“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 布局的书 深入涵盖了此类问题。如果您有兴趣了解整个系统的工作原理,那么值得您花时间。

The node <default/> is something called a "layout handle". Every request into Magent generates a number of these handles. Checkout the Layout tab on the Commerce Bug demo site to get an idea of the sorts of handles that get generated.

Magento merges all layout XML files into one giant tree called the package layout. Then, handles determine which Layout XML Update fragments are used for a particular request. These fragments are combined into the Page Layout. As you intuited, the <default/> handle is always added, which is why you're borking every site in your system.

The bad news is while there's a handle for CMS pages, (<cms_page_view />), it would still be an all or nothing affair. You could add something to all CMS pages, but not specific CMS pages. So yes, the Layout Update XML section of the CMS admin is "the right" way to do what you want.

The good news is there's two approaches you can take that are cleaner than what you've come up with so far. First, you can clean things up a little bit by defining your own handle in your XML file, and then use a special Layout XML command to include that handle.

In your XML, add your Layout Update XML fragment inside a custom handle.

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

Then in the CMS Admin, add the following Layout Update XML for the pages you want

<update handle="my_fancy_pants_unique_handle_name_which_doesnt_conflict_with_existing_names" />

Magento allows Layout Update XML fragments to add additional handles to the request. That's what you're doing above. This cleans things up a bit, and if you wanted to change some of the XML, there's a centralized place for it.

Update: It turns out that that the <update/> command can only be used from the Layout XML files themselves. The code that loads the Layout Update XML for CMS pages isn't the same code that loads and processes updates for the XML files. Magento will literally add anything in the CMS form as a Layout update. It won't processes it for recursive updates. So, adding something like this to local.xml would work

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

But you can't do that directly with an update applied via the CMS admin. Live and learn.

All that said, the widget approach is probably still viable, and an alternative to the above would be.

  1. Create a custom module with a custom block class

  2. The block class renders no HTML

  3. The block class contains a single method named something like "addFooToLayout"

Then, in your CMS page, add an update like this

<block type="yourmodule/yourblock" name="unique_name" alias="unique_name">
    <action method="addFooToLayout" />
</block>

and then in your block definition

public addFooToLayout()
{
    $layout = Mage::getSingleton('core/layout');
    $head   = $layout->getBlock('head');
    $head->addItem('skin_js','js/sw/wall.js');
    //etc...
}

Something like that should work and is a little clearer (depending on how much Layout Update XML you want to add). However, I haven't tested it and my credibility's blown on this one so buyer beware.

The second approach is to create a single widget that encompasses what you'd like to add to the page, and then use the Widget Instance admin to add that widget to specific blocks on specific pages. That links should get you started.

Finally, at the risk of being a shill, I've recently self-published a book on Magento Layouts that covers these sorts of issues in depth. It's worth your time if you're interested in understanding how the entire system works.

你另情深 2024-11-10 17:12:18

不过这个问题已经很老了,我通过谷歌找到了它,并想为将来阅读这篇文章的人添加一些信息。

昨天,当我读到这个问题和答案时,还有 this这个帖子,我变得相当确保不可能或很难仅针对特定页面覆盖/扩展 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>

将任何自定义布局句柄注入到任何页面非常容易,并且仅对使用此模板和自定义布局句柄的页面执行您想要的任何操作。我希望我之前就知道这一点,希望这篇文章能够节省某人的时间。

Nevertheless this question is quite old already, I found it through google and would like to add some information for those who will read this post in future.

Yesterday when I read this question and answer, and also this and this posts, I became quite sure that it is not possible or quite hard to override/extend the CMS page layout handle only for specific pages. That led me to developing one small extension, which injects any custom layout handle in any specific page. I will update this post with a public link to the extension soon.

But then I discovered that it is actually possible to just create a new template for CMS page and assign any custom layout handle to that template, see this question and answer from Marius for example. Here is the important bit of that code sample:

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

It is quite easy to inject any custom layout handle to any page and do whatever you want only with pages which use this template and your custom layout handle. I wish I knew that before, hope this post will save someone's time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文