Posting in the Magento forums has been disabled pending the implementation of a new and improved forum solution which should better serve the community.

For new questions please post at magento.stackexchange.com, the community-run support site for the Magento community. We will be providing updates on the new forum solution soon. For questions or concerns please email community@magento.com.

Magento Forum

foreach collection problem
 
Lyndon_Corleone
Jr. Member
 
Total Posts:  27
Joined:  2012-08-15
 

I write a custom extension to export orders,and change the Adminhtml/Block/sales/Order/grid.php.

I find if I add a ‘foreach($collection as $order){}’ in _prepareCollection function ,the filter data which for search wouldn’t be effective,if I

remove the code,the filter data become effective again.It’s Magento ver. 1.6.2.0

Does anybody has the same problem?

 
Magento Community Magento Community
Magento Community
Magento Community
 
tzyganu
Mentor
 
Avatar
Total Posts:  2205
Joined:  2009-11-18
Bucharest, Romania
 

Hello
You are having this problem because the filters and limits (pagination) are added in the parent::_prepareCollection method before the collection is loaded (I mean before the actual sql is called). After the collection is loaded any modification to filters and limits are useless.

You can try this approach. I’m not sure if it works but you can try it:
So the method looks like this:

protected function _prepareCollection()
    
{
        $collection 
Mage::getResourceModel($this->_getCollectionClass());
        
$this->setCollection($collection);
        return 
parent::_prepareCollection();
    
}
You should try to add your foreach look after calling parent::_prepareCollection.
Something like this:
protected function _prepareCollection()
    
{
        $collection 
Mage::getResourceModel($this->_getCollectionClass());
        
$this->setCollection($collection);
        
parent::_prepareCollection();
        foreach (
$collection as $order){
            
//do something here
        
}
        
return $this;
    
}
Or you can try putting your custom code in the method _afterLoadCollection();

In the _prepareCollection method from this class Mage_Adminhtml_Block_Widget_Grid there is this piece of code:

if (!$this->_isExport{
                $this
->getCollection()->load();
                
$this->_afterLoadCollection();
            
}
so the _afterLoadCollection method is called after loading the collection items (captain obvious smile );

Marius.

 
Magento Community Magento Community
Magento Community
Magento Community
 
BelVG
Guru
 
Avatar
Total Posts:  306
Joined:  2011-02-16
Minsk, Belarus
 

Hi,

This happens because all the filters are set up before the collection is loaded.

protected function _prepareCollection()
    
{
        
if ($this->getCollection()) {

            $this
->_preparePage();

            
$columnId $this->getParam($this->getVarNameSort(), $this->_defaultSort);
            
$dir      $this->getParam($this->getVarNameDir(), $this->_defaultDir);
            
$filter   $this->getParam($this->getVarNameFilter(), null);

            if (
is_null($filter)) {
                $filter 
$this->_defaultFilter;
            
}

            
if (is_string($filter)) {
                $data 
$this->helper('adminhtml')->prepareFilterString($filter);
                
$this->_setFilterValues($data);
            
}
            
else if ($filter && is_array($filter)) {
                $this
->_setFilterValues($filter);
            
}
            
else if(!== sizeof($this->_defaultFilter)) {
                $this
->_setFilterValues($this->_defaultFilter);
            
}

            
if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir 
= (strtolower($dir)=='desc') ? 'desc' 'asc';
                
$this->_columns[$columnId]->setDir($dir);
                
$this->_setCollectionOrder($this->_columns[$columnId]);
            
}

            
if (!$this->_isExport{
                $this
->getCollection()->load();
                
$this->_afterLoadCollection();
            
}
        }

        
return $this;
    
}

If you download the collection, and then try to apply filters, they will not work.
Download the collection is either a call to load (), or when using it in a cycle (like you have ) foreach($collection as $order){}

Depending on the functionality you require, you can either:
- Create a new collection based on data derived from the use of the cycle.
- Use a loop after filters applying


  
parent::_prepareCollection();
  foreach(
$collection as $order){}
  
return $this;
)
 
Magento Community Magento Community
Magento Community
Magento Community
 
Lyndon_Corleone
Jr. Member
 
Total Posts:  27
Joined:  2012-08-15
 
tzyganu - 21 November 2012 04:12 AM

Hello
You are having this problem because the filters and limits (pagination) are added in the parent::_prepareCollection method before the collection is loaded (I mean before the actual sql is called). After the collection is loaded any modification to filters and limits are useless.

You can try this approach. I’m not sure if it works but you can try it:
So the method looks like this:

protected function _prepareCollection()
    
{
        $collection 
Mage::getResourceModel($this->_getCollectionClass());
        
$this->setCollection($collection);
        return 
parent::_prepareCollection();
    
}
You should try to add your foreach look after calling parent::_prepareCollection.
Something like this:
protected function _prepareCollection()
    
{
        $collection 
Mage::getResourceModel($this->_getCollectionClass());
        
$this->setCollection($collection);
        
parent::_prepareCollection();
        foreach (
$collection as $order){
            
//do something here
        
}
        
return $this;
    
}
Or you can try putting your custom code in the method _afterLoadCollection();

In the _prepareCollection method from this class Mage_Adminhtml_Block_Widget_Grid there is this piece of code:
if (!$this->_isExport{
                $this
->getCollection()->load();
                
$this->_afterLoadCollection();
            
}
so the _afterLoadCollection method is called after loading the collection items (captain obvious smile );

Marius.

Great! This works !Thanks a lot, Marius!

 
Magento Community Magento Community
Magento Community
Magento Community
 
Lyndon_Corleone
Jr. Member
 
Total Posts:  27
Joined:  2012-08-15
 
BelVG - 21 November 2012 04:17 AM

Hi,

This happens because all the filters are set up before the collection is loaded.

protected function _prepareCollection()
    
{
        
if ($this->getCollection()) {

            $this
->_preparePage();

            
$columnId $this->getParam($this->getVarNameSort(), $this->_defaultSort);
            
$dir      $this->getParam($this->getVarNameDir(), $this->_defaultDir);
            
$filter   $this->getParam($this->getVarNameFilter(), null);

            if (
is_null($filter)) {
                $filter 
$this->_defaultFilter;
            
}

            
if (is_string($filter)) {
                $data 
$this->helper('adminhtml')->prepareFilterString($filter);
                
$this->_setFilterValues($data);
            
}
            
else if ($filter && is_array($filter)) {
                $this
->_setFilterValues($filter);
            
}
            
else if(!== sizeof($this->_defaultFilter)) {
                $this
->_setFilterValues($this->_defaultFilter);
            
}

            
if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir 
= (strtolower($dir)=='desc') ? 'desc' 'asc';
                
$this->_columns[$columnId]->setDir($dir);
                
$this->_setCollectionOrder($this->_columns[$columnId]);
            
}

            
if (!$this->_isExport{
                $this
->getCollection()->load();
                
$this->_afterLoadCollection();
            
}
        }

        
return $this;
    
}

If you download the collection, and then try to apply filters, they will not work.
Download the collection is either a call to load (), or when using it in a cycle (like you have ) foreach($collection as $order){}

Depending on the functionality you require, you can either:
- Create a new collection based on data derived from the use of the cycle.
- Use a loop after filters applying

  
parent::_prepareCollection();
  foreach(
$collection as $order){}
  
return $this;
)

Hi,thanks for your suggestion! The new approach is helpful!

 
Magento Community Magento Community
Magento Community
Magento Community
Magento Community
Magento Community
Back to top