开发者

Magento JoinLeft() in custom orders grid causing SQL integrity constrain violation for non-admin user in multi-website setup

I have extended the Mage_Adminhtml_Block_Sales_Order_Grid class with a custom module to add several customer attributes (Magento EE 1.10) to the grid.

I added the custom attributes to the collection in my MyCompany_MyModule_Block_Adminhtml_Order_Grid class in the _prepareCollection() method using three joins like this:

protected function _prepareCollection()
{
    $collection = Mage::getResourceModel($this->_getCollectionClass());

    //get the table names for the customer attributes we'll need
    $customerEntityVarchar = Mage::getSingleton('core/resource')
        ->getTableName('customer_entity_varchar');
    $customerEntityInt = Mage::getSingleton('core/resource')
开发者_JAVA技巧        ->getTableName('customer_entity_int');
    // add left joins to display the necessary customer attribute values
    $collection->getSelect()->joinLeft(array(
        'customer_entity_int_table'=>$customerEntityInt), 
        '`main_table`.`customer_id`=`customer_entity_int_table`.`entity_id`
            AND `customer_entity_int_table`.`attribute_id`=148', 
        array('bureau'=>'value'));
    $collection->getSelect()->joinLeft(array(
        'customer_entity_varchar_table'=>$customerEntityVarchar), 
        '`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
            AND `customer_entity_varchar_table`.`attribute_id`=149', 
        array('index_code'=>'value'));
    $collection->getSelect()->joinLeft(array(
        'customer_entity_varchar_2_table'=>$customerEntityVarchar), 
        '`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id` 
            AND `customer_entity_varchar_2_table`.`attribute_id`=150', 
        array('did_number'=>'value'));
    $this->setCollection($collection);
    return parent::_prepareCollection();
}

UPDATE: While everything displays fine when viewing orders, things are not fine when I try to search / filter orders by any of the text join fields (index_code or did_number). The result is a SQL error: "SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'store_id' in where clause is ambiguous."

This problem also exists if I remove all but one of the leftJoin() statements, so something is going wrong with both (either) of the joins with the customer_entity_varchar table.


As now there are two columns with the name store_id, you have to specify filter_index when you add the column to the grid:

$this->addColumn('store_id', array(
  ...
  'filter_index'=>'main_table.store_id',

));

So that it knows which one you are referring while filtering.

I hope it helps!


More than likely it is because you are joining customer_entity_varchar_table twice.

$collection->getSelect()->joinLeft(array(
    'customer_entity_varchar_table'=>$customerEntityVarchar), 
    '`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
        AND `customer_entity_varchar_table`.`attribute_id`=149', 
    array('index_code'=>'value'));
$collection->getSelect()->joinLeft(array(
    'customer_entity_varchar_2_table'=>$customerEntityVarchar), 
    '`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id` 
        AND `customer_entity_varchar_2_table`.`attribute_id`=150', 
    array('did_number'=>'value'));

You may want to combine those, you can also try and print the SQL to see what the Query looks like:

$collection->getSelect()->getSelectSql();

More info on collections: http://blog.chapagain.com.np/magento-collection-functions/


The problem appears to exist in two different places. One case is if logged in as a user with a single store, the other as a user who can filter various stores.

Single store user

The solution I went with was to override the addAttributeToFilter method on the collection class. Not knowing exactly what changing the Enterprise_AdminGws_Model_Collections::addStoreAttributeToFilter method would affect other behavior I wanted to avoid that, and I found adding a filter index in Mage_Adminhtml_Block_Sales_Order_Grid as Javier suggested did not work.

Instead I added the following method to Mage_Sales_Model_Resource_Order_Grid_Collection:

/**
 * {@inheritdoc}
 */
public function addAttributeToFilter($attribute, $condition = null)
{
    if (is_string($attribute) && 'store_id' == $attribute) {
        $attribute = 'main_table.' . $attribute;
    }
    return parent::addFieldToFilter($attribute, $condition);
}

A patch can be found here: https://gist.github.com/josephdpurcell/baf93992ff2d941d02c946aeccd48853

Multi-store user

If a user can filter orders by store at admin/sales_order, the following change is also needed to Mage_Adminhtml_Block_Sales_Order_Grid around line 75:

    if (!Mage::app()->isSingleStoreMode()) {
        $this->addColumn('store_id', array(
            'header'    => Mage::helper('sales')->__('Purchased From (Store)'),
            'index'     => 'store_id',
            'type'      => 'store',
            'store_view'=> true,
            'display_deleted' => true,
            'filter_index' => 'main_table.store_id',
        ));
    } 

A patch can be found here: https://gist.github.com/josephdpurcell/c96286a7c4d2f5d1fe92fb36ee5d0d5a


I had the same bug, after grepping the code, I finally found the troublemaker which is in the Enterprise_AdminGws_Model_Collections class at line ~235:

/**
 * Add store_id attribute to filter of EAV-collection
 *
 * @param Mage_Eav_Model_Entity_Collection_Abstract $collection
 */
public function addStoreAttributeToFilter($collection)
{
    $collection->addAttributeToFilter('store_id', array('in' => $this->_role->getStoreIds()));
}

You have to replace 'store_id' by 'main_table.store_id', of course you'll have to extend that particular method in your own rewrite to stick into Magento guidelines :p

Hope it helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜