【问题标题】:magento limiting number of returned items in product collection callmagento 限制产品集合调用中返回项目的数量
【发布时间】:2011-02-20 16:46:09
【问题描述】:

我试图在 list.phtml 模板的副本中手动限制返回结果的数量,但结果比我预期的要困难得多。

我尝试手动设置集合大小,但又没有任何效果。有人可以告诉我如何做到这一点吗?将不胜感激!

【问题讨论】:

  • 您是想限制退回产品的数量以便只显示特定数量,还是出于其他原因?
  • 我正在尝试扩展这个模块yoast.com/landing-pages-module-magento 我的意思是扩展,即使只是在我制作的自定义list.php页面上手动写入,调用一定数量的产品,以便我可以拥有例如,来自 x 类别的 3 个特色产品、来自 y 的 3 个、来自 z 的 3 个特色产品,并使其在 jquery 滑块中显示得非常漂亮。

标签: php collections magento pagination


【解决方案1】:

看起来 list.phtml 中返回的集合已经调用了 load(),这意味着当我们到达模板时,我们已经失去了设置页面大小的机会。所以,这会变得有点混乱!

生成该集合的块是Mage_Catalog_Block_Product_List,我们可以用我们自己的类扩展它并同时覆盖它。创建一个扩展 Mage_Catalog_Block_Product_List 的新块并覆盖方法 _getProductCollection,如下所示:

/**
 * Retrieve loaded category collection
 *
 * @return Mage_Eav_Model_Entity_Collection_Abstract
 */
protected function _getProductCollection()
{
    if (is_null($this->_productCollection)) {
        $layer = Mage::getSingleton('catalog/layer');
        /* @var $layer Mage_Catalog_Model_Layer */
        if ($this->getShowRootCategory()) {
            $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
        }

        // if this is a product view page
        if (Mage::registry('product')) {
            // get collection of categories this product is associated with
            $categories = Mage::registry('product')->getCategoryCollection()
                ->setPage(1, 1)
                ->load();
            // if the product is associated with any category
            if ($categories->count()) {
                // show products from this category
                $this->setCategoryId(current($categories->getIterator()));
            }
        }

        $origCategory = null;
        if ($this->getCategoryId()) {
            $category = Mage::getModel('catalog/category')->load($this->getCategoryId());
            if ($category->getId()) {
                $origCategory = $layer->getCurrentCategory();
                $layer->setCurrentCategory($category);
            }
        }
        $this->_productCollection = $layer->getProductCollection();

        $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

        // OUR CODE MODIFICATION ////////////////////
        $yourCustomPage = someFunctionThatDetectsYourCustomPage();
        if($yourCustomPage) {
            $this->_productCollection->setPageSize(1);
            $this->_productCollection->setCurPage(3);
            $this->_productCollection->load();
        }
        /////////////////////////////////////////////

        if ($origCategory) {
            $layer->setCurrentCategory($origCategory);
        }
    }
    return $this->_productCollection;
}

重要的部分是找到某种方法来检测您是否在使用自定义 list.phtml 页面。然后你需要在你的类的布局中覆盖对<block type='catalog/product_list' />的引用,你应该准备好了。

希望有帮助!

谢谢, 乔

【讨论】:

  • 嗨,乔,感谢您的回复。好的,我可以把它放在自定义 list.php 文件(我用来制作登录页面)中,在其他代码之前还是我需要把它放在其他地方?我基本上只是扩展这个模块; yoast.com/landing-pages-module-magento -- 允许限制返回的项目数量,这样我就可以制作漂亮的登录页面。我对 someFunctionThatDetectsYourCustomPage(); 部分有点困惑-- 我是先在landing.php 页面上调用该函数,然后再调用其他函数吗? (对不起,我对 OO PHP 和 Zend 还是很陌生。)
  • 感谢@Joseph 的建议-我在回答中对其进行了一些调整,以使其不那么突兀且更具前瞻性。京东
【解决方案2】:

不幸的是,它不起作用,因为在 _getProductCollection() 方法中,集合已经用页面大小进行了初始化。

更灵活的解决方案可能是观察catalog_product_collection_load_before 事件,顾名思义,该事件在加载集合之前调度。

下面是一个例子(假设在yourpackage下写一个yourmodule扩展):

第 1 步:在 config.xml 中定义您的观察者

在您的config.xml 扩展文件的global 部分中插入如下内容:

<events>
  <catalog_product_collection_load_before>
    <observers>
      <yourpackage_yourmodule_catalog_observer>
        <type>singleton</type>
        <class>yourpackage_yourmodule/catalog_observer</class>
        <method>limitPageSize</method>
      </yourpackage_yourmodule_catalog_observer>
    </observers>
  </catalog_product_collection_load_before>
</events>    

第 2 步:在 Model\Catalog 文件夹下定义您的 Observer 类:

<?php
class Yourpackage_Yourmodule_Model_Catalog_Observer
{
  public function limitPageSize($observer)
  {
    #TODO: Insert the logic you need to differentiate when to apply the following
    $event = $observer->getEvent();
    $collection = $event->getCollection();
    $collection->setPageSize(3);
    return $this;
  }
}

希望对您有所帮助。 真挚地, 亚历山德罗·朗奇

【讨论】:

    【解决方案3】:

    使用此方法I recently discovered 是一种快速的方法。您甚至可以直接在模板中使用它。

    $_productCollection = clone $this->getLoadedProductCollection();
    $_productCollection->clear()
                       ->setPageSize(3)
                       ->load();
    

    【讨论】:

    • 这很好,但确实意味着 SQL 调用被执行了两次。请参阅下面的答案以获取替代方法。
    • @Jonathan - 你当然是对的。预防胜于治疗。
    【解决方案4】:

    与@joseph 类似的方法是覆盖Mage_Catalog_Block_Product_List,但在新类中插入以下代码:

    const PAGE_SIZE = 3;
    
    protected function _getProductCollection(){
        $collection = parent::_getProductCollection();
        $yourCustomBoolean = someFunctionThatDetectsYourCustomPage();
        if($yourCustomBoolean) {
            $collection->setPageSize(self::PAGE_SIZE);
        }
        return $collection;
    }
    

    这样,您将从父块继承 Mage_Catalog 代码中的任何未来更改,但仍设置您的页面限制。

    理想情况下,您应该使用system.xml 节点来创建管理员可以编辑的字段,而无需对 page_size 进行硬编码。 xml 看起来像:

    <config>
    <sections>
        <catalog>
            <groups>
                <frontend>
                    <fields>
                        <custom_page_size translate="label">
                            <label>Page Size for Custom Page Type</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>9999</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </custom_page_size>
                    </fields>
                </frontend>
            </groups>
        </catalog>
    </sections>
    </config>
    

    然后在您的代码中检索该值:

    $page_size = Mage::getStoreConfig('catalog/frontend/custom_page_size');
    

    HTH,
    京东

    【讨论】:

    • 这太好了,您能否提供一个简短的建议,说明我将如何实施someFunctionThatDetectsYourCustomPage()?我有一个自定义模块,它使用类别页面作为其基础,我试图仅限制该模块的产品数量。但我不知道如何在观察者功能中检测到我正在查看该模块的类别页面,而不是网站上的任何其他类别页面。谢谢!
    • 听起来您应该在模块中使用自定义控制器,而不是(ab)使用类别页面...
    • 非常真实,乔纳森。然而,我继承了这个代码库,它的规模太大了,目前无法更改。我一直在使用clockworkgeek的解决方案,但肯定更愿意实施你的解决方案;我只是不确定如何检测用户是否在我的特定模块的类别页面上。
    • 听起来很有趣 :) 如果你查看这篇 @chapagain 博客文章,blog.chapagain.com.np/… 会给你一些指导。此外,检查 Mage::registry('current_category') 以查看类别控制器是否已经为您将类别隐藏在注册表中。
    【解决方案5】:

    我得到了 User:clockworkgeek 的代码,但是这里有一些问题,正确的代码如下,它可以工作,感谢clockworkgeek。

    $_productCollection = $this->getLoadedProductCollection();
    $_productCollection->clear();
    $_productCollection->setPageSize(3)
    $_productCollection->load();
    

    你也写enter code here或者修改为解决这个问题

    $this->getLoadedProductCollection()->clear();
    $_productCollection = $this->getLoadedProductCollection();
    

    谢谢, 如果对您有帮助,请发表评论。

    【讨论】:

      【解决方案6】:

      如前所述,productCollection 已经设置了页面大小。不过,还有另一种获取收藏的方法;通过catalog/product 模特:

      $productCollection = Mage::getModel('catalog/product')
          ->getCollection()
          ->addAttributeToSelect(
              array('name', 'image', 'price')
          )
          ->addIdFilter( 
              array('1', '2')
          )
          ->setPageSize( 2 )
          ->load();
      ;
      
      return $productCollection->getSelect()->__toString();
      

      生成的查询(最终是 object)包含 LIMIT 语法:

      SELECT `e`.* ... WHERE (`e`.`entity_id` IN('1', '2')) LIMIT 2;
      

      这是你问的吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-03
        • 1970-01-01
        相关资源
        最近更新 更多