0

我正在尝试为 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>

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

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

编辑

解决了

通过@b.enoit.be 的解释,我尝试了以下设置......它正在运行;-)

应用程序/etc/modules/Mynamespace_Mymodulname.xml:

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

应用程序/代码/本地/Mynamespace/Mymodulname/Block/Index.php:

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

应用程序/代码/本地/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"}}

应用程序/设计/前端/myTheme/default/mynamespace/myoutput.phtml:

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

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

4

2 回答 2

3

如果这些myNamespace_myModulname确实是您在实际代码中所拥有的,请首先查看@fantasticrice答案

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

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

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

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

那么有效的块类是

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

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

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

(看看我如何用斜杠替换下划线并用.php扩展名添加后缀?)。

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

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

1.把手

当您为模块定义 config.xml 时,您必须知道某些部分是“固定的”,而某些部分是“句柄”
这意味着 Magento 期望某些部分具有有限的可能性,例如frontend or adminhtml or globalblocks, models, helpers, ... there is more here有些只是为您的模块命名并在 Magento 下调用它或处理它。

在这里,您在 config.xml 中说,对于<global>配置(前端和后端(= admin)的意思) -已修复- 您希望将模块的块添加到 Magento 的现有<blocks>-已修复- 列表中这将由--handle --引用,<mynamespace_mymodulename>然后将映射到所有类都以 . 开头的文件Mynamespace_Mymodulename_Block

这是您自己的模块块所需类型的第一部分。
mynamespace_mymodulename相当于 MagentoMynamespace_Mymodulename_Block

2.右挡

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

现在我们有了类型的第二部分,我们只需要用斜杠组合它们:mynamespace_mymodulename/index

因此,您必须将您在 cms 中的呼叫更改为:

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

希望有了这个,它会起作用。

注意 1/3:正如@fantasticrice所指出的,我还建议您遵循类的命名约定:

Zend Framework 标准化了类命名约定,其中类的名称直接映射到存储它们的目录。(...)

类名只能包含字母数字字符。类名中允许使用数字,但在大多数情况下不鼓励使用。下划线只能代替路径分隔符;文件名“Zend/Db/Table.php”必须映射到类名“Zend_Db_Table”。

如果一个类名由多个单词组成,则每个新单词的第一个字母必须大写。不允许连续的大写字母,例如“Zend_PDF”类是不允许的,而“Zend_Pdf”是可以接受的。

这些约定为 Zend Framework 定义了一个伪命名空间机制。Zend Framework 将在 PHP 命名空间功能可用并且我们的开发人员可以在他们的应用程序中使用时采用它。

有关此类名约定的示例,请参见标准库和附加库中的类名。

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

注意2/3:再次按照约定,只有类将具有大写的文件名/文件夹结构。因此,您的模板文件夹和文件根本不应该有资本。

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


TL;博士

应用程序/代码/本地/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;
    }
}

内容管理系统内容

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

应用程序/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; ?>
于 2015-06-01T22:04:37.673 回答
1

我注意到这里有几个问题,所以我将尝试解决您在问题中发布的内容可以看到的问题,尽管您要完成的工作并不完全清楚,您可能会受益最多从阅读有关 Magento 的布局、块和模板的指南

  1. 您当前的类名不遵循Magento 自动加载器命名约定,您会注意到ucwords()每个路径元素都使用了该约定。你的类名应该是这样的:Mynamespace_Mymodulename_Block_Myblockname,它会映射到文件app/code/.../Mynamespace/Mymodulename/Block/Myblockname.php。您的配置 XML 应该更新以匹配。

  2. 您的 CMS 指令当前不使用您的新块类型,因为如果您希望在模板中使用块的自定义逻辑,它会设置为type="core/template"应该使用的时间。type="Mynamespace_Mymodulename/Myblockname"您的模板代码未显示,但这可能是调用getCollection()模板不起作用的原因。

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

于 2015-06-01T21:51:08.363 回答