Spalte zu einem Raster hinzufügen (Beobachter) - Spalte 'store_id' in where-Klausel ist nicht eindeutig

16

Ich füge dem Ordnungsraster eine Spalte mit dem Beobachter-Ansatz hinzu:

  1. Zum Ereignis -> sales_order_grid_collection_load_beforeIch füge der Sammlung einen Join hinzu
  2. Zum Ereignis -> core_block_abstract_prepare_layout_beforeIch füge eine Spalte zum Raster hinzu

BEARBEITEN Weitere Informationen:

Bei Ereignis (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'));

}

Bei Ereignis (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');
}

Alles funktioniert einwandfrei, bis ich das Raster mit dem Filter für die Speicheransicht filtere : Spalte 'store_id' in der where-Klausel ist ein mehrdeutiges Problem

Ich habe die Abfrage gedruckt:

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')

Wie Sie sehen store_id, main_tableAlias verpassen .

Um dies zu erreichen, muss ich nur die filter_indexSpalte für die Speicher-ID festlegen, aber über den Beobachter. Die Frage ist also, wie ich es im laufenden Betrieb tun kann .
Ohne die Blockklasse zu überschreiben ? (Andernfalls ist der Beobachteransatz unbrauchbar.)

Fra
quelle

Antworten:

32

Versuchen wir es noch einmal mit einer anderen Lösung, die ich bereits erwähnt habe :-), ich habe die vollständige Erweiterung erstellt, um Ihnen zu zeigen, wie Sie das Feld zur Rastertabelle hinzufügen können. Danach benötigen Sie nur noch eine Layoutaktualisierungsdatei, um die Spalte zu Ihrer Bestellgitterseite hinzuzufügen.

Ich habe die Erweiterung Example_SalesGrid aufgerufen, aber Sie können sie an Ihre eigenen Bedürfnisse anpassen.

Beginnen wir damit, das Modul init xml in /app/etc/modules/Example_SalesGrid.xml zu erstellen :

<?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>

Als nächstes erstellen wir unser Modul config xml in /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>

Jetzt erstellen wir das SQL-Upgrade-Skript in /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();

Als Nächstes erstellen wir die Layout-Aktualisierungsdatei in /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>

Jetzt benötigen wir zwei Blockdateien , eine zum Erstellen der Filteroptionen: /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;
    }
}

Und der zweite, der die Zeilenwerte in den korrekten Text übersetzt, der angezeigt wird :

<?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;
    }
}

Die zuletzt benötigte Datei wird nur benötigt, wenn Sie eine zusätzliche Spalte aus einer anderen Tabelle als sales / order (sales_flat_order) erstellen. Alle Felder in sales / order_grid, die dem Spaltennamen aus sales / order entsprechen, werden in der Tabelle sales / order_grid automatisch aktualisiert. Wenn Sie beispielsweise die Zahlungsoption hinzufügen müssen, muss dieser Beobachter das Feld zur Abfrage hinzufügen, damit die Daten in die richtige Tabelle kopiert werden können. Der hierfür verwendete Beobachter befindet sich in /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'
        //);
    }
}

Dieser Code basiert auf dem Beispiel von http://www.ecomdev.org/2010/07/27/adding-order-attribute-to-orders-grid-in-magento-1-4-1.html

Hoffe das obige Beispiel löst dein Problem.

Vladimir Kerkhoff
quelle
Es tut mir leid, dass ich es auf Reisen nicht testen konnte ... Es klingt etwas komplizierter, als ich mich nähere (funktioniert es auch für neue Bestellungen?)
Fr
Der Grid Observer behandelt die Datenänderungen bei jeder Änderung, da dies eine native Magento-Verwendung ist und Sie keine Verknüpfungen mit anderen Tabellen erstellen müssen. Dies beschleunigt die Abfrage bei großen Bestellmengen (alle Daten werden in sales_flat_order_grid gespeichert).
Vladimir Kerkhoff
Wenn ich dies versuche und verwende, erhalte ich die Fehlermeldung Warnung: Fehlendes Argument 2 für Varien_Db_Adapter_Pdo_Mysql :: quoteInto ()
Vaishal Patel
4

Versuchen Sie, diese zu verwenden:

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);
    }
}
mageUz
quelle
1
Dies hätte als Antwort auf den Beobachteransatz des OP wirklich akzeptiert werden müssen.
musicliftsme
2

Benötigen Sie in Ihrer Methode wirklich salesOrderGridCollectionLoadBeforeden folgenden Code $collection->addFilterToMap('store_id', 'main_table.store_id');? Wenn nicht, entfernen Sie es und versuchen Sie Folgendes:

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'));
    }
}
Sylvain Rayé
quelle
Bereits beide ausprobiert :( Column('store_id');ist nicht verfügbar auf core_block_abstract_prepare_layout_before (_prepareColumn () wird aufgerufen, daher ist die Spalte zu diesem Zeitpunkt nicht vorhanden) addFilterToMapnicht erledigt ist Job
Fra
Irgendeine Idee, warum addFilterToMap nicht funktioniert?
Fr
Soory Ich hatte in den letzten Tagen nicht allzu viel Zeit, mich umzusehen. Vielleicht morgen. Nur eine Idee, weil ich mich ein wenig an den Grund erinnere, warum ich gesagt habe, dass ich addFilterToMap nicht verwende, ist, wie Sie möglicherweise falsch verwenden, Parameter sind falsch oder werden nicht im richtigen Moment verwendet. Es sind nur Ideen von Erinnerungen.
Sylvain Rayé
2

Anstelle des statischen Spaltennamens können Sie die folgende Methode für alle Spalten verwenden. Ich kann verstehen, wenn Sie die Antwort von mageUz verwenden, die für eine Spalte funktioniert, und wenn Sie sich für eine andere Spalte entscheiden, wird möglicherweise derselbe Fehler angezeigt. Der folgende Code gibt Ihnen die Lösung für alle Spalten gleichzeitig.

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);
}
jyotiranjan.in
quelle