Ajouter une colonne à une grille (observateur) - Colonne « store_id » dans la clause where est question ambiguë

magento.stackexchange https://magento.stackexchange.com/questions/4191

Question

J'ajoute une colonne à la grille de commande en utilisant l'approche d'observateur:

  1. Sur l'événement -> sales_order_grid_collection_load_before J'ajoute une jointure à la collection
  2. Sur l'événement -> core_block_abstract_prepare_layout_before J'ajoute une colonne à la grille

EDIT Plus d'info:

Sur l'événement (1):

   public function salesOrderGridCollectionLoadBefore($observer)
{
    $collection = $observer->getOrderGridCollection();
    $collection->addFilterToMap('store_id', 'main_table.store_id');
    $select = $collection->getSelect();
    $select->joinLeft(array('oe' => $collection->getTable('sales/order')), 'oe.entity_id=main_table.entity_id', array('oe.customer_group_id'));

}

Sur événement (2):

public function appendCustomColumn(Varien_Event_Observer $observer)
{
    $block = $observer->getBlock();
    if (!isset($block)) {
        return $this;
    }

    if ($block->getType() == 'adminhtml/sales_order_grid') {
        /* @var $block Mage_Adminhtml_Block_Customer_Grid */
        $this->_addColumnToGrid($block);
    }
}

protected function _addColumnToGrid($grid)
{

    $groups = Mage::getResourceModel('customer/group_collection')
        ->addFieldToFilter('customer_group_id', array('gt' => 0))
        ->load()
        ->toOptionHash();
    $groups[0] = 'Guest';


    /* @var $block Mage_Adminhtml_Block_Customer_Grid */
    $grid->addColumnAfter('customer_group_id', array(
        'header' => Mage::helper('customer')->__('Customer Group'),
        'index' => 'customer_group_id',
        'filter_index' => 'oe.customer_group_id',
        'type' => 'options',
        'options' => $groups,
    ), 'shipping_name');
}

Tout travail bien jusqu'à ce que je filtre la grille avec filtre vue magasin: Colonne « store_id » dans la clause where est question ambiguë

J'ai imprimé la requête:

SELECT `main_table`.*, `oe`.`customer_group_id` 
FROM `sales_flat_order_grid` AS `main_table`
LEFT JOIN `sales_flat_order` AS `oe` ON oe.entity_id=main_table.entity_id 
WHERE (store_id = '5') AND (oe.customer_group_id = '6')

Comme vous le cas, voir store_id miss alias main_table.

Pour ce faire, je juste besoin de régler la filter_index pour le magasin colonne Id mais par l'observateur La question est de savoir comment puis-je faire à la volée
sans écraser le bloc classe? (Sinon l'approche d'observateur est inutile)

Était-ce utile?

La solution

Essayons à nouveau avec une autre solution sur je l'ai mentionné avant de vous :-), j'ai construire l'extension complète pour vous montrer comment ajouter le champ à la table de la grille. Après cela, vous avez seulement besoin d'un fichier de mise à jour de mise en page pour ajouter la colonne à vous commander la page du réseau.

J'appelle l'extension Example_SalesGrid, mais vous pouvez changer à vos propres besoins.

Soit Commençons par la création du module d'initialisation xml /app/etc/modules/Example_SalesGrid.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!--
 Module bootstrap file
-->
<config>
    <modules>
        <Example_SalesGrid>
            <active>true</active>
            <codePool>community</codePool>
            <depends>
                <Mage_Sales />
            </depends>
        </Example_SalesGrid>
    </modules>
</config>

Ensuite, nous créons notre module config xml /app/code/community/Example/SalesGrid/etc/config.xml :

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Example_SalesGrid>
            <version>0.1.0</version> <!-- define version for sql upgrade -->
        </Example_SalesGrid>
    </modules>
    <global>
        <models>
            <example_salesgrid>
                <class>Example_SalesGrid_Model</class>
            </example_salesgrid>
        </models>
        <blocks>
            <example_salesgrid>
                <class>Example_SalesGrid_Block</class>
            </example_salesgrid>
        </blocks>
        <events>
            <!-- Add observer configuration -->
            <sales_order_resource_init_virtual_grid_columns>
                <observers>
                    <example_salesgrid>
                        <model>example_salesgrid/observer</model>
                        <method>addColumnToResource</method>
                    </example_salesgrid>
                </observers>
            </sales_order_resource_init_virtual_grid_columns>
        </events>
        <resources>
            <!-- initialize sql upgrade setup -->
            <example_salesgrid_setup>
                <setup>
                    <module>Example_SalesGrid</module>
                    <class>Mage_Sales_Model_Mysql4_Setup</class>
                </setup>
            </example_salesgrid_setup>
        </resources>
    </global>
    <adminhtml>
        <layout>
            <!-- layout upgrade configuration -->
            <updates>
                <example_salesgrid>
                    <file>example/salesgrid.xml</file>
                </example_salesgrid>
            </updates>
        </layout>
    </adminhtml>
</config>

Maintenant, nous créons le script de mise à niveau sql /app/code/community/Example/SalesGrid/sql/example_salesgrid_setup/install-0.1.0.php :

<?php
/**
 * Setup scripts, add new column and fulfills
 * its values to existing rows
 *
 */
$this->startSetup();
// Add column to grid table

$this->getConnection()->addColumn(
    $this->getTable('sales/order_grid'),
    'customer_group_id',
    'smallint(6) DEFAULT NULL'
);

// Add key to table for this field,
// it will improve the speed of searching & sorting by the field
$this->getConnection()->addKey(
    $this->getTable('sales/order_grid'),
    'customer_group_id',
    'customer_group_id'
);

// Now you need to fullfill existing rows with data from address table

$select = $this->getConnection()->select();
$select->join(
    array('order'=>$this->getTable('sales/order')),
    $this->getConnection()->quoteInto(
        'order.entity_id = order_grid.entity_id'
    ),
    array('customer_group_id' => 'customer_group_id')
);
$this->getConnection()->query(
    $select->crossUpdateFromSelect(
        array('order_grid' => $this->getTable('sales/order_grid'))
    )
);

$this->endSetup();

Ensuite, nous créons le fichier de mise à jour de mise en page /app/design/adminhtml/default/default/layout/example/salesgrid.xml:

<?xml version="1.0"?>
<layout>
    <!-- main layout definition that adds the column -->
    <add_order_grid_column_handle>
        <reference name="sales_order.grid">
            <action method="addColumnAfter">
                <columnId>customer_group_id</columnId>
                <arguments module="sales" translate="header">
                    <header>Customer Group</header>
                    <index>customer_group_id</index>
                    <type>options</type>
                    <filter>Example_SalesGrid_Block_Widget_Grid_Column_Customer_Group</filter>
                    <renderer>Example_SalesGrid_Block_Widget_Grid_Column_Renderer_Customer_Group</renderer>
                    <width>200</width>
                </arguments>
                <after>grand_total</after>
            </action>
        </reference>
    </add_order_grid_column_handle>
    <!-- order grid action -->
    <adminhtml_sales_order_grid>
        <!-- apply the layout handle defined above -->
        <update handle="add_order_grid_column_handle" />
    </adminhtml_sales_order_grid>
    <!-- order grid view action -->
    <adminhtml_sales_order_index>
        <!-- apply the layout handle defined above -->
        <update handle="add_order_grid_column_handle" />
    </adminhtml_sales_order_index>
</layout>

Maintenant, nous avons besoin de deux fichiers de blocs, un pour créer les options de filtre, /app/code/community/Example/SalesGrid/Block/Widget/Grid/Column/Customer/Group.php:

<?php

class Example_SalesGrid_Block_Widget_Grid_Column_Customer_Group extends Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Select  {

    protected $_options = false;

    protected function _getOptions(){

        if(!$this->_options) {
            $methods = array();
            $methods[] = array(
                'value' =>  '',
                'label' =>  ''
            );
            $methods[] = array(
                'value' =>  '0',
                'label' =>  'Guest'
            );

            $groups = Mage::getResourceModel('customer/group_collection')
                ->addFieldToFilter('customer_group_id', array('gt' => 0))
                ->load()
                ->toOptionArray();

            $this->_options = array_merge($methods,$groups);
        }
        return $this->_options;
    }
}

Et la seconde à traduire les valeurs de la ligne au texte correct qui sera affiché, /app/code/community/Example/SalesGrid/Block/Widget/Grid/Column/Renderer/Customer/Group.php :

<?php

class Example_SalesGrid_Block_Widget_Grid_Column_Renderer_Customer_Group extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract   {

    protected $_options = false;

    protected function _getOptions(){

        if(!$this->_options) {
            $methods = array();
            $methods[0] = 'Guest';

            $groups = Mage::getResourceModel('customer/group_collection')
                ->addFieldToFilter('customer_group_id', array('gt' => 0))
                ->load()
                ->toOptionHash();
            $this->_options = array_merge($methods,$groups);
        }
        return $this->_options;
    }

    public function render(Varien_Object $row){
        $value = $this->_getValue($row);
        $options = $this->_getOptions();
        return isset($options[$value]) ? $options[$value] : $value;
    }
}

Le dernier fichier nécessaire est uniquement nécessaire si vous créez une colonne supplémentaire à partir d'une autre table que les ventes / ordre (sales_flat_order). Tous les champs de ventes / order_grid correspondant au nom de la colonne de la vente / commande est automatiquement mis à jour dans la vente / order_grid table. Si vous avez besoin d'ajouter l'option de paiement par exemple, vous aurez besoin cet observateur pour ajouter le champ à la requête afin que les données peuvent être copiées sur la bonne table. L'observateur utilisé pour cela est /app/code/community/Example/SalesGrid/Model/Observer.php :

<?php
/**
 * Event observer model
 *
 *
 */
class Example_SalesGrid_Model_Observer {

    public function addColumnToResource(Varien_Event_Observer $observer) {
        // Only needed if you use a table other than sales/order (sales_flat_order)

        //$resource = $observer->getEvent()->getResource();
        //$resource->addVirtualGridColumn(
        //  'payment_method',
        //  'sales/order_payment',
        //  array('entity_id' => 'parent_id'),
        //  'method'
        //);
    }
}

Ce code est basé sur l'exemple de http://www.ecomdev.org/2010/07/27/adding-order-attribute-to-orders-grid-in-magento-1-4 -1.html

Hope l'exemple ci-dessus permet de résoudre votre problème.

Autres conseils

Essayez d'utiliser celles-ci:

public function salesOrderGridCollectionLoadBefore($observer)
{
    /**
     * @var $select Varien_DB_Select
     */
    $collection = $observer->getOrderGridCollection();
    $collection->addFilterToMap('store_id', 'main_table.store_id');
    $select     = $collection->getSelect();
    $select->joinLeft(array('oe' => $collection->getTable('sales/order')), 'oe.entity_id=main_table.entity_id', array('oe.customer_group_id'));
    if ($where = $select->getPart('where')) {
        foreach ($where as $key=> $condition) {
            if (strpos($condition, 'store_id')) {
                $value       = explode('=', trim($condition, ')'));
                $value       = trim($value[1], "' ");
                $where[$key] = "(main_table.store_id = '$value')";
            }
        }
        $select->setPart('where', $where);
    }
}

Avez-vous vraiment besoin dans votre méthode salesOrderGridCollectionLoadBefore le $collection->addFilterToMap('store_id', 'main_table.store_id'); de code suivant? Sinon retirez-le et essayez ce qui suit:

protected function _addColumnToGrid($grid)
{
....... // here you code from your post above

    $storeIdColumn = $grid->getColumn('store_id');

    if($storeIdColumn) {
        $storeIdColumn->addData(array('filter_index' => 'main_table.store_id'));
    }
}

Au lieu d'utiliser le nom de la colonne statique vous pouvez utiliser ci-dessous pour toute méthode colonne. Je peux comprendre si on utilise la réponse de mageUz qui fonctionnera pour une colonne et si vous allez pour une autre colonne, vous pourriez obtenir même erreur. Donc, ci-dessous le code vous donne la solution pour toutes les colonnes simultanément.

public function salesOrderGridCollectionLoadBefore(Varien_Event_Observer $observer)
{
    $collection = $observer->getOrderGridCollection();
    $select = $collection->getSelect();
    $select->joinLeft(array('order' => $collection->getTable('sales/order')), 'order.entity_id=main_table.entity_id',array('shipping_arrival_date' => 'shipping_arrival_date'));

    if ($where = $select->getPart('where')) {
        foreach ($where as $key=> $condition) {
            $parsedString = $this->get_string_between($condition, '`', '`');
    $yes = $this->checkFiledExistInTable('order_grid',$parsedString);
    if($yes){
        $condition = str_replace('`','',$condition);
        $where[$key] = str_replace($parsedString,"main_table.".$parsedString,$condition);
    }
        }
        $select->setPart('where', $where);
    }
}

 public function checkFiledExistInTable($entity=null,$parsedString=null){
   $resource = Mage::getSingleton('core/resource');
   $readConnection = $resource->getConnection('core_read');

    if($entity == 'order'){
       $table = 'sales/order';
    }elseif($entity == 'order_grid'){
        $table = 'sales/order_grid';
    }else{
        return false;
    }

     $tableName = $resource->getTableName($table);
    $saleField = $readConnection->describeTable($tableName);

    if (array_key_exists($parsedString,$saleField)){
       return true;
   }else{
      return false;
   }
 }

function get_string_between($string, $start, $end){
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top