Magento:在 CMS 中调用自定义块

Magento: call a custom block in CMS

我正在尝试为 Magento 1.9.1 创建自己的模块。在我的模块中,我尝试像这样在 CMS 内容中调用块:

{{block type="core/template" template="myNamespace/myModulOutput.phtml"}}

myModulOutput.phtml 模板包含来自我自己的控制器的集合:

class myNamespace_myModelname_Block extends Mage_Core_Block_Template
{
    public function getCollection()
    {
       // some code
        return $collection;
    }
}

该模块似乎处于活动状态并使用此配置显示在 Magento 后端中:

<config>
    <modules>
        <myNamespace_myModulname>
            <version>0.1.0</version>
        </myNamespace_myModulname>
    </modules>
    <global>
        <blocks>
            <myNamespace_myModulname> 
                <class>myNamespace_myModulname_Block</class>
            </myNamespace_myModulname>
        </blocks>
    </global>
</config>

块 class 在文件 app/code/local/myNamespace/myModulname/Blocks/Index.php 中定义。

这是一个有效的配置吗?我在前端收到错误消息:Fatal error: Call to a member function getCollection() on a non-object.

编辑

已解决

根据@b.enoit.be 的解释,我尝试了以下设置...它是 运行 ;-)

app/etc/modules/Mynamespace_Mymodulname.xml:

<?xml version="1.0"?>
<config>
    <modules>
        <Mynamespace_Mymodulname>
            <active>true</active>
            <codePool>local</codePool>
            <depends/>
        </Mynamespace_Mymodulname>
    </modules>
</config>

app/code/local/Mynamespace/Mymodulname/Block/Index.php:

    <?php
    class Mynamespace_Mymodulname_Block_Index extends Mage_Core_Block_Template
    {
        public function getTest()
        {
           // some code
            return "mymodul:test";
        }
    }
    ?>

app/code/local/Mynamespace/Mymodulname/etc/config.xml:

<?xml version="1.0"?>
<config>
    <modules>
        <Mynamespace_Mymodulname>
            <version>0.1.0</version>
        </Mynamespace_Mymodulname >
    </modules>
    <global>
        <blocks>
            <mynamespace_mymodulname> 
                <class>Mynamespace_Mymodulname_Block</class>
            </mynamespace_mymodulname >
        </blocks>
    </global>
</config>

CMS-调用

{{block type="mynamespace_mymodulname/index" template="mynamespace/myoutput.phtml"}}

app/design/frontend/myTheme/default/mynamespace/myoutput.phtml:

<?php /** @var $this Mynamespace_Mymodulname_Block_Index */ ?>
<?php echo $this->getTest() ?>

非常感谢如此详细而有意义的解释:-)

我注意到这里有几个问题,所以我将尝试解决您在问题中发布的内容可以看到的问题,尽管您想要完成的事情并不完全清楚,并且您可能会从阅读 guide about Magento’s layout, blocks, and templates:

中获益最多
  1. 您当前的 class 名称不遵循 Magento autoloader naming conventions,您会注意到在每个路径元素上使用 ucwords()。您的 class 名称应该类似于:Mynamespace_Mymodulename_Block_Myblockname,它将映射到文件 app/code/.../Mynamespace/Mymodulename/Block/Myblockname.php。您的配置 XML 应该更新以匹配。

  2. 你的 CMS 指令目前没有使用你的新块类型,因为它被设置为 type="core/template",而如果你想使用它应该是 type="Mynamespace_Mymodulename/Myblockname"你的块在你的模板中的自定义逻辑。您的模板代码未显示,但这可能是在您的模板中调用 getCollection() 无效的原因。

如果您展示更多您的作品,我们可能会提供更多帮助。

如果那些 myNamespace_myModulname 确实是您实际代码中的内容,请先查看

然后,如果我们认为您的代码具有正确的命名约定(请参阅此 post 末尾的注释),首先,这不是一个有效的块 class :

class Mynamespace_Mymodulename_Block extends Mage_Core_Block_Template{ /* ... */ }

如果像您稍后所说的那样,您的文件位于

app/code/local/Mynamespace/Mymodulename/Block/Index.php

那么有效区块class是

class Mynamespace_Mymodulename_Block_Index extends Mage_Core_Block_Template{ /* ... */ }

因为 Magento 中的 class 名称应该始终 遵循与文件路径完全相同的体系结构 (控制器除外,但我们根本不是在谈论控制器使用您在此处提供给我们的代码)=>

class Mynamespace_Mymodulename_Block_Index === Mynamespace/Mymodulename/Block/Index.php

(看看我是如何用斜杠替换下划线并 post 用 .php 扩展名解决这个问题的?)。

那么你真正想要的是你的视图mynamespace/mymoduleoutput.phtml使用你自己的模块。
为此,您必须为您的块指定正确的类型

类型由 config.xml 中定义的句柄和块文件路径的组合定义。

1。句柄

当你为一个模块定义一个config.xml时,你必须知道有些部分是"fixed"有些部分是"handles".
这意味着 Magento 期望某些部分具有有限数量的可能性,例如frontend or adminhtml or globalblocks, models, helpers, ... there is more here 和一些只是名称来为您的模块添加别名并调用它或处理我们在 Magento 下的调用。

这里你在 config.xml 中说 <global> 配置(意味着前端和后端(= admin))-- fixed - - 你想添加到 Magento 的现有 <blocks> -- fixed -- -- 将引用的模块块的列表handle -- <mynamespace_mymodulename> 然后将映射到 classes 都以 Mynamespace_Mymodulename_Block.[= 开头的文件42=]

这是您想要的 type 模块的第一部分。
mynamespace_mymodulename 等同于 Magento 的 Mynamespace_Mymodulename_Block

2。右方块

然后你只需要指出从你的块的根文件夹到 Magento 的正确路径,这将与你的 folders/files 架构完全相同,再一次:所以在你的情况下,只是 index.
因此,正如您现在可能理解的那样,Magento 将在文件 Mynamespace/Mymodulename/Block/Index.php 中查找 class Mynamespace_Mymodulename_Block_Index(句柄 + '_' + 指定块)。
但是,如果您的文件在 app/code/local/Mynamespace/Mymodulename/Block/Path/To/File.php 下,您将拥有 path_to_file => class Mynamespace_Mymodulename_Block_Path_To_File、文件 Mynamespace/Mymodulename/Block/Path/To/File.php

现在我们有了 type 的第二部分,我们只需要 assemble 加上斜线即可:mynamespace_mymodulename/index

因此您必须将您在 cms 中的调用更改为:

{{block type="mynamespace_mymodulename/index" template="mynamespace/mymoduleoutput.phtml"}}

希望它能奏效。

NOTE 1/3 : 正如@fantasticrice所指出的,我也建议你遵循[=的命名约定144=]:

Zend Framework standardizes on a class naming convention whereby the names of the classes directly map to the directories in which they are stored. (...)

Class names may only contain alphanumeric characters. Numbers are permitted in class names but are discouraged in most cases. Underscores are only permitted in place of the path separator; the filename "Zend/Db/Table.php" must map to the class name "Zend_Db_Table".

If a class name is comprised of more than one word, the first letter of each new word must be capitalized. Successive capitalized letters are not allowed, e.g. a class "Zend_PDF" is not allowed while "Zend_Pdf" is acceptable.

These conventions define a pseudo-namespace mechanism for Zend Framework. Zend Framework will adopt the PHP namespace feature when it becomes available and is feasible for our developers to use in their applications.

See the class names in the standard and extras libraries for examples of this classname convention.

来源:http://framework.zend.com/manual/1.12/en/coding-standard.naming-conventions.html

注意 2/3 : 再次按照约定,只有 class 将具有大写的文件名/文件夹结构。所以,你的模板文件夹和文件根本不应该有大写字母。

注意 3/3 : 在 Magento 中,同样,按照惯例,我们不在句柄中使用大写字母。


TL;DR

app/code/local/Mynamespace/Mymodulename/etc/config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Mynamespace_Mymodulename>
            <version>0.1.0</version>
        </Mynamespace_Mymodulename>
    </modules>
    <global>
        <blocks>
            <mynamespace_mymodulename> 
                <class>Mynamespace_Mymodulename_Block</class>
            </mynamespace_mymodulename>
        </blocks>
    </global>
</config>

app/code/local/Mynamespace/Mymodulename/Block/Index.php

<?php
class Mynamespace_Mymodulename_Block_Index extends Mage_Core_Block_Template
{
    public function getCollection()
    {
       // some code
        return $collection;
    }
}

CMS 内容

{{block type="mynamespace_mymodulename/index" template="mynamespace/mymoduleoutput.phtml"}}

app/etc/modules/Mynamespace_Mymodulename.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Mynamespace_Mymodulename>
            <active>true</active>
            <codePool>local</codePool>
            <depends/>
        </Mynamespace_Mymodulename>
    </modules>
</config>

app/design/frontend/base/default/template/mynamespace/mymoduleoutput.phtml

<?php /** @var $this Mynamespace_Mymodulename_Block_Index */ ?>
<?php foreach($this->getCollection() as $item): ?>
    <?php //do something ?>
<?php endforeach; ?>