Magento collections when setPageSize and pagination does not work
We decided to write about a problem that sometimes occurs everywhere where collections are used: goods, news, blog, etc.The problem is that you are trying to set a limit for the collection, but it does not work, so pagination does not work either. If you select any page, you are always on the first page where all the records are displayed.
Below you can see the code in which the problem is located. This is a function that adds comments to every news.
it is necessary to optimize to one query or, at best, information about comments ( the amount) is written, collected by a separate process in a separate column, in order to this data is available immediately
in the Magento collection use the Lazy Load pattern delayed download, i mean downloading data will start when you use foreach, count. For this you need to be careful when you are needlessly going to “run” through the array.
<?php
/**
* Add comments to collection
*
* @param CommerceLab_News_Model_Mysql4_News_Collection $collection
* @return $this
*/
private function addCommentToCollection($collection){
foreach ($collection as $item) {
$comments = Mage::getModel(‘clnews/comment’)->getCollection()
->addNewsFilter($item->getNewsId())
->addApproveFilter(CommerceLab_News_Helper_Data::APPROVED_STATUS);
$item->setCommentsCount(count($comments));
}
return $this;
}
?>
In this case, the data will be loaded and processed to a class that implements the pagination, if the data has already been loaded, then processing will not happen for the second time.
Pattern Varien_Data_Collection implements functions from interfaces IteratorAggregate, Countable which will load the data.
<?php
class Varien_Data_Collection implements IteratorAggregate, Countable {
/**
* Implementation of IteratorAggregate::getIterator()
*/
public function getIterator()
{
$this->load();
return new ArrayIterator($this->_items);
}
/**
* Retireve count of collection loaded items
*
* @return int
*/
public function count()
{
$this->load();
return count($this->_items);
}
}
?>
Correct option
Set the flag for loading data – information about comments and after the data is downloaded – it is important to add information about the comments.
<?php
class Extension_News_Model_Mysql4_News_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
{
/**
* Load with comment count flag
*
* @var boolean
*/
protected $_loadWithCommentCount = false;
/**
* Set flag for loading product count
*
* @param boolean $flag
* @return $this
*/
public function setLoadCommentCount($flag)
{
$this->_loadWithCommentCount = $flag;
return $this;
}
public function load($printQuery = false, $logQuery = false)
{
parent::load($printQuery, $logQuery);
if ($this->_loadWithCommentCount === true){
$this->_loadCommentCount();
}
return $this;
}
/**
* Add information about comments – count
* @return $this
*/
protected function _loadCommentCount(){
foreach ($this->_items as $item){
$select = $this->_conn->select();
$select->from(
$this->getTable(‘news/comment’),
new Zend_Db_Expr(‘COUNT(DISTINCT comment_id)’)
)
->where(‘news_id =?’, $item->getId())
->where(‘comment_status =?’, CommerceLab_News_Helper_Data::APPROVED_STATUS)
;
$item->setCommentsCount(intval($this->_conn->fetchOne($select)));
}
return $this;
}
}