Magento - 扩展 Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection 类

发布于 2024-09-26 02:15:31 字数 2678 浏览 3 评论 0原文

好的,这是我最近在这里问的另一个问题的引申。基本上,我想扩展 Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection 类,这样我就可以为产品集合添加一些额外的过滤器,这些过滤器可以在整个商店中重复使用(例如畅销产品)。这是为了替换我当前使用的以下代码,该代码位于我的 template.phtml 文件中:

$_bs_productCollection = Mage::getResourceModel('reports/product_collection')
->addAttributeToSelect('name')
->addAttributeToFilter('visibility', $visibility)
->addOrderedQty()
->setOrder('ordered_qty', 'desc')
->setPageSize(6);
$_bs_productCollection->load();

因此,我设置了我的模块,并且正在加载它(它显示在 admin/system/config/advanced 中)。文件夹结构如下:

etc/modules/Samsmodule.xml
local/Samsmodule
local/Samsmodule/Catalog
local/Samsmodule/Catalog/etc
   local/Samsmodule/Catalog/etc/config.xml
local/Samsmodule/Catalog/Model
   local/Samsmodule/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php
local/Samsmodule/Catalog/Helper (not sure if this is needed or not)

我的 Samsmodule.xml 是:

<config>
<modules>
    <Samsmodule_Catalog>
        <active>true</active>
        <codePool>local</codePool>
    </Samsmodule_Catalog>
</modules>
</config>

我的 config.xml 是:

<config>
<modules>
    <Samsmodule_Catalog>
        <version>0.1.0</version>
    </Samsmodule_Catalog>
</modules>
<global>
    <models>
        <catalog_resource_eav_mysql4>
            <rewrite>
                <product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</product_collection>
            </rewrite>
        </catalog_resource_eav_mysql4>
    </models>
</global>
</config>

我的 Collection.php 是:

<?php

class Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

{
public function filterbyBestSelling($attribute,$visibility,$_category,$no_of_items)
{
    $this->addAttributeToSelect($attribute)->addOrderedQty()->setOrder('ordered_qty', 'desc')->addAttributeToFilter('visibility', $visibility)->addCategoryFilter($_category)->setPageSize($no_of_items);
    return $this;
}
}

然后从我的模板.phtml 我这样称呼它:

$_bs_productCollection = Mage::getResourceModel('reports/product_collection')
->filterbyBestSelling('name',$visibility,$_category,6);

但它不起作用 - 我错过了什么?如果我只是将 Collection.php 中的代码添加到核心 Collection.php 文件的底部,并使用相同的调用,它就可以正常工作。

OK, so this is leading on from another question I asked here recently. Basically, I want to extend the Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection class, so I can add some extra filters for the product collections that can be re-used throughout my store (such as best-selling). This is meant to replace the following code, which I currently use, which is in my template.phtml file:

$_bs_productCollection = Mage::getResourceModel('reports/product_collection')
->addAttributeToSelect('name')
->addAttributeToFilter('visibility', $visibility)
->addOrderedQty()
->setOrder('ordered_qty', 'desc')
->setPageSize(6);
$_bs_productCollection->load();

So, I set up my module, and it's loading (it shows in the admin/system/config/advanced). Folder structure as follows:

etc/modules/Samsmodule.xml
local/Samsmodule
local/Samsmodule/Catalog
local/Samsmodule/Catalog/etc
   local/Samsmodule/Catalog/etc/config.xml
local/Samsmodule/Catalog/Model
   local/Samsmodule/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php
local/Samsmodule/Catalog/Helper (not sure if this is needed or not)

My Samsmodule.xml is:

<config>
<modules>
    <Samsmodule_Catalog>
        <active>true</active>
        <codePool>local</codePool>
    </Samsmodule_Catalog>
</modules>
</config>

My config.xml is:

<config>
<modules>
    <Samsmodule_Catalog>
        <version>0.1.0</version>
    </Samsmodule_Catalog>
</modules>
<global>
    <models>
        <catalog_resource_eav_mysql4>
            <rewrite>
                <product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</product_collection>
            </rewrite>
        </catalog_resource_eav_mysql4>
    </models>
</global>
</config>

And my Collection.php is:

<?php

class Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

{
public function filterbyBestSelling($attribute,$visibility,$_category,$no_of_items)
{
    $this->addAttributeToSelect($attribute)->addOrderedQty()->setOrder('ordered_qty', 'desc')->addAttributeToFilter('visibility', $visibility)->addCategoryFilter($_category)->setPageSize($no_of_items);
    return $this;
}
}

And then from my template.phtml I call it like so:

$_bs_productCollection = Mage::getResourceModel('reports/product_collection')
->filterbyBestSelling('name',$visibility,$_category,6);

But it's not working - what am I missing? If I just add the code from my Collection.php to the bottom of my core Collection.php file, and use the same call, it works fine.

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

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

发布评论

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

评论(2

不打扰别人 2024-10-03 02:15:31

(并不是想让你挂在另一个线程上,但是这个问题没有一个快速的答案,既不会看起来像魔术,也不会让人进一步感到困惑。)

你不需要重写一个类,除非你'我们将更改现有方法的行为。您只需要创建一个扩展现有类的新类。下面是你如何做到这一点。

事物正常状态的术语

  1. 模型是定义 Magento 中某些“事物”(产品等)行为的逻辑类/对象

  2. 包含模型资源。模型资源是从某些数据存储(mysql 等)实际获取数据的类。这就是数据映射器模式。

  3. 集合是具有类似数组属性的对象,它们查询数据库并返回一组模型。有点令人困惑的是,集合也是模型资源。

因此,在正常情况下,您可能会说

Mage::getModel('catalog/product')

获取产品模型,底层系统使用

Mage::getResourceModel('catalog/product');

它来获取查询单个产品的模式资源对象,并且以下任一是用于

Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/product')->getCollection();

获取查询多个模型的 Collection 对象。在当前版本的 Magento 中,每个模型对象都有一个名为“getCollection”的方法,该方法返回其相应的集合资源。

偏离轨道的报告

报告有点偏离轨道,但一切仍然在同一个宇宙中,如上所述。事实证明,不存在这样的模型

Mage::getModel('reports/product');

但是有一个集合

Mage::getResourceModel('reports/product_collection')

如果您查看该类(您将在下面扩展它),您将看到“reports/product_collection”集合

class Mage_Reports_Model_Mysql4_Product_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

<扩展了基本产品集合类。换句话说,负责报告部分的客户端程序员所做的与您完全相同。 “我想向 Mage::getModelResource('catalog/product_collection') 添加一些方法。他们通过扩展基类来做到这一点。

闭嘴,我只是想因此

,您真正想要做的是

  1. 创建一个新类Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection来扩展基本Mage_Reports_Model_Mysql4_Product_Collection集合类

  2. 确保调用 Mage::getModelResource('samscatalog/product_collection')。通过配置我们的模块以使用模型和模型资源来返回上述类的实例

我们还将稍微更改您的模块结构,以帮助缓解命名混乱。我不太喜欢为模块文件夹提供与核心模块相同的名称(即“目录”),并且顶级文件夹(在 local/ 之后)实际上是一个命名空间,而不是模块文件夹。 (一个命名空间可能包含许多模块)

我们不会覆盖该类。我们正在您的命名空间下配置一个自定义模块以使用模型和模型资源。然后我们定义一个模型资源来扩展系统中已有的 PHP 类。仅当您想要更改特定方法调用的行为时才应使用覆盖。 (很抱歉对此喋喋不休,但社区中对此有足够多的普遍困惑,值得一遍又一遍地反复讨论。)

首先,我们将创建模块目录结构和文件。我们只需要两个

local/Samsnamespace/Samscatalog/etc/config.xml
local/Samsnamespace/Samscatalog/Model/Mysql4/Product/Collection.php

(并且不要忘记在 app/etc/modules 中启用该模块。如果您不确定这意味着什么,开始阅读)

Collection.php 文件应包含

<?php
class Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection    
{
    /* your custom methods go here*/
}

并且配置文件应包含

<config>
    <modules>
        <Samsnamespace_Samscatalog>
            <version>0.1.0</version>
        </Samsnamespace_Samscatalog>
    </modules>
    <global>
        <models>
            <samscatalog>
                <class>Samsnamespace_Samscatalog_Model</class>
                <resourceModel>samscatalog_mysql4</resourceModel>
            </samscatalog>

            <samscatalog_mysql4>
                <class>Samsnamespace_Samscatalog_Model_Mysql4</class>
            </samscatalog_mysql4>
        </models>
    </global>
</config>

这些文件就位并启用模块后,您应该能够调用

$test = Mage::getResourceModel('samscatalog/product_collection');           
var_dump(get_class($test));

和您的收藏将被归还,您可以随心所欲地添加方法。

这是怎么回事

这是令人费解的,所以如果你愿意,你可以停止阅读。这也是我在其他地方介绍过的概念的重述。

当你说

Mage::getResourceModel('samscatalog/product_collection');

底层法师系统代码说“好吧,所以这个资源模型”

samscatalog/product_collection

samscatalog/product

模型的一部分(在这种情况下并不完全正确,但这是系统的想法)。

因此,由于资源模型 samscatalog/product_collectionsamscatalog/product 模型的一部分,让我们查看一下配置

global/models/samscatalog/resourceModel

,获取资源模型 URI

samscatalog_mysql4

,然后使用它查看配置

global/models/samscatalog_mysql4/class

以获取属于此模块的所有资源模型的基类名。这最终是

Samsnamespace_Samscatalog_Model_Mysql4

这意味着 samscatalog/product_collection 资源模型被命名

Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection

,然后它只是 Magento 的标准自动加载,它执行

include('Samsnamespace/Samscatalog/Model/Mysql4/Product/Collection.php');

(Didn't mean to leave you hanging in the other thread, but there's not a quick answer to this one that wouldn't either seem like magic or just confuse people further.)

You don't need to override a class unless you're going to change the behavior of an existing method. You just need to create a new class that extend the existing class. Here's how you do that.

Terminology For the Normal State of Things

  1. Models are the logical classes/objects that define the behavior of some "thing" (product, etc.) in Magento

  2. Models contain Model Resources. Model Resources are the classes that do the actual fetching of data from some datastore (mysql, etc). This is the Data Mapper pattern.

  3. Collections are objects with array like properties that query the database and return a group of Models. Somewhat confusingly, Collections are also Model Resources.

So, in the normal state of things, you might say something like

Mage::getModel('catalog/product')

to get a product model and the underlying system uses

Mage::getResourceModel('catalog/product');

to get the Mode Resource object that queries for a single product, and either of the following are used

Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/product')->getCollection();

to get the Collection object that queries for many models. In current versions of Magento each Model object has a method named "getCollection" which returns its corresponding Collection Resource.

Reports Off the Rails

Reports go a little sideways, but everything is still within the same universe as described above. It turns out there's no such model as a

Mage::getModel('reports/product');

But there is a collection

Mage::getResourceModel('reports/product_collection')

If you look at the class (which you'll be extending below), you'll see that the 'reports/product_collection' collection

class Mage_Reports_Model_Mysql4_Product_Collection extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection

extends the the base product collection class. In other words, the client programmer working on the reports section had the exact same though you did. "I want to add some methods to to Mage::getModelResource('catalog/product_collection'). They did this by extending the base class.

Shut Up, I Just Want this to Work

So, what you really want to do here is

  1. Create a new class Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection that extends the base Mage_Reports_Model_Mysql4_Product_Collection collection class.

  2. Ensure that a call to Mage::getModelResource('samscatalog/product_collection') returns an instance of the above class by configurig our module to use Models and Model Resources.

We're also going to change you Module structure around a little bit to help ease naming confusion. I'm not a big fan of giving module folders the same names as core modules (i.e. "Catalog"), and the top level folder (after local/) is actually a Namespace, not a module folder. (A namespace may contain many modules)

We are not overriding the class. We are configuring a custom module under your namespace to use both Models and Model Resources. We're then defining a model resource that extends an existing PHP class already in the system. Overrides should only be used when you want to change the behavior of a particular method call. (Appologies for harping on this, but there's enough general confusion in the communiy about this that it's worth harping on over. and over. and over.)

First, we're going to create the module directory structure and files. We'll just need two

local/Samsnamespace/Samscatalog/etc/config.xml
local/Samsnamespace/Samscatalog/Model/Mysql4/Product/Collection.php

(and don't forget to enable the module in app/etc/modules. If you're not sure what that means, start reading)

The Collection.php file should contain

<?php
class Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection    
{
    /* your custom methods go here*/
}

And the config file should contain

<config>
    <modules>
        <Samsnamespace_Samscatalog>
            <version>0.1.0</version>
        </Samsnamespace_Samscatalog>
    </modules>
    <global>
        <models>
            <samscatalog>
                <class>Samsnamespace_Samscatalog_Model</class>
                <resourceModel>samscatalog_mysql4</resourceModel>
            </samscatalog>

            <samscatalog_mysql4>
                <class>Samsnamespace_Samscatalog_Model_Mysql4</class>
            </samscatalog_mysql4>
        </models>
    </global>
</config>

With these files in place and the module enabled, you should be able to call

$test = Mage::getResourceModel('samscatalog/product_collection');           
var_dump(get_class($test));

and your collection will be returned, and you can add methods to your heart's content.

What's Going On

This is mind bending, so you can stop reading if you want. It's also a rehash of concepts I've covered elsewhere.

When you say

Mage::getResourceModel('samscatalog/product_collection');

The underlying mage system codes says "ok, so this resource model"

samscatalog/product_collection

is part of the

samscatalog/product

model (not entirely true in this case, but it's what the system thinks).

So, since the resource model samscatalog/product_collection is part of the samscatalog/product model, let's look at the config at

global/models/samscatalog/resourceModel

To get the resource model URI of

samscatalog_mysql4

and then let's use that to look at the config at

global/models/samscatalog_mysql4/class

to get the base classname for all Resource Models that are a part of this Module. This ends up being

Samsnamespace_Samscatalog_Model_Mysql4

Which means the samscatalog/product_collection Resource Model is named

Samsnamespace_Samscatalog_Model_Mysql4_Product_Collection

and then its just Magento's standard auto-load which does a

include('Samsnamespace/Samscatalog/Model/Mysql4/Product/Collection.php');
亣腦蒛氧 2024-10-03 02:15:31

最终产品系列属于什么类别?你的覆盖有效吗?

这一部分似乎很可疑,如果它确实有效,我会感到惊讶:

<global>
    <models>
        <catalog_resource_eav_mysql4>
            <rewrite>
                <product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</product_collection>
            </rewrite>
        </catalog_resource_eav_mysql4>
    </models>
</global>

试试这个:

<global>
    <models>
        <catalog>
            <rewrite>
                <resource_eav_mysql4_product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</resource_eav_mysql4_product_collection>
            </rewrite>
        </catalog>
    </models>
</global>

里面的标签引用了一个模块。 Catalog 是一个模块,而catalog_resource_eav_mysql4 不是。内部的标签指定了一个类句柄,它基本上是类名中 Mage_Catalog_Model_ 之后的所有内容。

希望有帮助!

谢谢,

What is the class of the resulting product collection? Does your override work?

This section seems suspect, I'm surprised if it's actually working:

<global>
    <models>
        <catalog_resource_eav_mysql4>
            <rewrite>
                <product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</product_collection>
            </rewrite>
        </catalog_resource_eav_mysql4>
    </models>
</global>

Try this instead:

<global>
    <models>
        <catalog>
            <rewrite>
                <resource_eav_mysql4_product_collection>Samsmodule_Catalog_Model_Resource_Eav_Mysql4_Product_Collection</resource_eav_mysql4_product_collection>
            </rewrite>
        </catalog>
    </models>
</global>

The tag inside of refers to a module. Catalog is a module, while catalog_resource_eav_mysql4 isn't. The tag inside of specifies a class handle, which is basically everything after Mage_Catalog_Model_ in the classname.

Hope that helps!

Thanks,
Joe

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