Varien_Data_Collection分页不起作用

时间:2013-11-25 16:00:47

标签: magento collections pagination

我从头开始创建了一个Varien_Data_Collection:

$myCollection = new Varien_Data_Collection();

在向其添加一些项目$myCollection->addItem($fooItem);后,我尝试将其分页为:

$myCollection->setPageSize(3)->setCurPage(1);

但是当我显示集合时,它会显示集合中的所有项目,而不是第一页,第二页面。

$myItems = $myCollection->getItems();
foreach ($myItems as $item) {
    echo $item->getData('bar');
}

3 个答案:

答案 0 :(得分:1)

(非抽象)基类Varien_Data_Collection - 虽然它确实有setPageSizesetCurPage方法,但这些方法并未反映在迭代器的聚合中:

class Varien_Data_Collection implements IteratorAggregate, Countable
{
    ...

    /**
     * Implementation of IteratorAggregate::getIterator()
     */
    public function getIterator()
    {
        $this->load();
        return new ArrayIterator($this->_items);
    }

    ...

它将在任何案例中返回包含所有对象的ArrayIteatorload方法在这里没有改变btw:

    ...

    /**
     * Load data
     *
     * @return  Varien_Data_Collection
     */
    public function loadData($printQuery = false, $logQuery = false)
    {
        return $this;
    }

    ...

    /**
     * Load data
     *
     * @return  Varien_Data_Collection
     */
    public function load($printQuery = false, $logQuery = false)
    {
        return $this->loadData($printQuery, $logQuery);
    }

    ...

我认为这可以作为一个错误,因为公共接口让人认为magent集合对象Varien_Data_Collection提供了分页,而不是。

我没有搜索有关此问题的错误报告。解决方案是使用另一个迭代器进行分页,例如an answerHow to Paginate lines in a foreach loop with PHP中使用PHP LimitIterator概述:

/**
 * Class Varien_Data_Collection_Pagination
 *
 * Aggregates missing Pagination on Collection on getting the Iterator
 *
 * @author hakre <http://hakre.wordpress.com/>
 */
class Varien_Data_Collection_Pagination implements IteratorAggregate
{
    /**
     * @var Varien_Data_Collection
     */
    private $collection;

    public function __construct(Varien_Data_Collection $collection)
    {
        $this->collection = $collection;
    }

    public function getIterator()
    {
        $collection = $this->collection;
        if (FALSE === $size = $collection->getPageSize()) {
            return $collection;
        }

        $page = $collection->getCurPage();
        if ($page < 1) {
            return $collection;
        }

        $offset = $size * $page - $size;

        return new LimitIterator(new IteratorIterator($collection), $offset, $size);
    }
}

用法示例:

$collection = new Varien_Data_Collection();
$collectionIterator = new Varien_Data_Collection_Pagination($collection);

# [...] fill collection 

# set pagination:
$collection->setPageSize(3);
$collection->setCurPage(1);

echo iterator_count($collectionIterator); # 3 (int) 

请记住,这主要是一个例子。恕我直言,这应该在Magento代码库的上游修复,所以你可能值得在Magento Bug-Tracker进行一些搜索工作。

答案 1 :(得分:0)

如前文所述,Varien_Data_collection不支持分页。一种解决方案是扩展此类并覆盖其loadData()方法。这是stdating stdClass对象数组的实际示例。可以与任何数据数组一起使用

类YourNamespace_YourModule_Model_History_Collection扩展了Varien_Data_Collection {

//array of stdClass objects. Can be array of any objects/subarrays
protected $_history = array();

public function loadData($printQuery = false, $logQuery = false){
    if ($this->isLoaded()) {
        return $this;
    }

    $this->_totalRecords = count($this->_history);

    $this->_setIsLoaded();

    // paginate and add items
    $from = ($this->getCurPage() - 1) * $this->getPageSize();
    $to = $from + $this->getPageSize() ;
    $isPaginated = $this->getPageSize() > 0;

    $cnt = 0;
    $sub_history = array_slice($this->_history, $from, $to-$from);
    foreach ( $sub_history as $entry) {
        $cnt++;

        $item = new $this->_itemObjectClass();
        //build here your Varien Object
        $item->setDate($entry->Date);
        //.......

        $this->addItem($item);
        if (!$item->hasId()) {
            $item->setId($cnt);
        }
    }

    return $this;
}

 public function setRecords($records){
    if(is_array($records)){ 
        $this->_history = $records;
    }
    return; 
 }

}

//你的块类

类YourNamespace_YourModule_Block_History扩展Mage_Core_Block_Template {

public function __construct(){
    $collection_prepared = new YourNamespace_YourModule_Model_History_Collection();
    //get your data here
    //$records is array of stdClass objects
    $collection_prepared->setRecords($records);

    $this->setCollection($collection_prepared); 
}

protected function _prepareLayout(){
    parent::_prepareLayout();

    $pager = $this->getLayout()->createBlock('page/html_pager', 'history.pager');
    $pager->setAvailableLimit(array(20=>20,40=>40,80=>80,'all'=>'all'));
    $pager->setCollection($this->getCollection()); 

    $this->setChild('pager', $pager);
    $this->getCollection()->load();
    return $this;
}

public function getPagerHtml()
{
    return $this->getChildHtml('pager');
}

}

希望这有帮助!

答案 2 :(得分:0)

class Pageable_Varien_Data_Collection extends Varien_Data_Collection
{
    /**
     * Load data
     *
     * @param   bool $printQuery
     * @param   bool $logQuery
     *
     * @return  Pageable_Varien_Data_Collection
     */
    public function load($printQuery = false, $logQuery = false)
    {
        if ($this->isLoaded()) {
            return $this;
        }
        $this->_renderLimit();
        $this->_setIsLoaded();
        return $this;
    }

    /**
     * @return  Pageable_Varien_Data_Collection
     */
    protected function _renderLimit()
    {
        if ($this->_pageSize) {
            $currentPage = $this->getCurPage();
            $pageSize = $this->_pageSize;
            $firstItem = (($currentPage - 1) * $pageSize + 1);
            $lastItem = $firstItem + $pageSize;
            $iterator = 1;
            foreach ($this->getItems() as $key => $item) {
                $pos = $iterator;
                $iterator++;
                if ($pos >= $firstItem && $pos <= $lastItem) {
                    continue;
                }
                $this->removeItemByKey($key);
            }
        }
        return $this;
    }

    /**
     * Retrieve collection all items count
     *
     * @return int
     */
    public function getSize()
    {
        if (is_null($this->_totalRecords)) {
            $this->_totalRecords = count($this->getItems());
        }
        return intval($this->_totalRecords);
    }

    /**
     * Retrieve collection items
     *
     * @return array
     */
    public function getItems()
    {
        return $this->_items;
    }
}