Додати стовпець до сітки (спостерігач) - стовпець «store_id», у якому пункт неоднозначний


16

Я додаю стовпчик до сітки замовлень за допомогою підходу спостерігача:

  1. На заході -> sales_order_grid_collection_load_before я додаю приєднання до колекції
  2. На події -> core_block_abstract_prepare_layout_beforeя додаю стовпчик до сітки

EDIT Детальніше:

На заході (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'));

}

На заході (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');
}

Все працює добре, поки я не відфільтрую сітку фільтром перегляду магазину: стовпець "store_id", де пункт неоднозначний

Я надрукував запит:

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

Як ви бачите, store_idміс main_tableпсевдонім.

Для цього мені просто потрібно встановити filter_indexстовпчик для зберігання Id, але через спостерігача . Питання полягає в тому, як я можу це зробити на ходу ?
Без переосмислення класу блоків ? (інакше підхід спостерігача марний)

Відповіді:


32

Давайте спробуємо це ще раз з іншим рішенням, про яке я говорив вам раніше :-), я створив повне розширення, щоб показати вам, як додати поле до таблиці сітки. Після цього вам знадобиться лише файл оновлення макета, щоб додати стовпець до сторінки замовлення сітки.

Я назвав розширення Example_SalesGrid, але ви можете змінити його на власні потреби.

Почнемо зі створення модуля init 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>

Далі ми створюємо наш модуль 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>

Тепер ми створюємо сценарій оновлення 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();

Далі ми створюємо файл оновлення макета в /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>

Тепер нам потрібні два файли блоку, один для створення параметрів фільтра, /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;
    }
}

А друге, щоб перевести значення рядків у правильний текст, який буде відображатися, /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;
    }
}

Останній потрібний файл потрібен лише у тому випадку, якщо ви створюєте додатковий стовпець із таблиці, яка не є продаж / замовлення (sales_flat_order). Усі поля продажів / замовлення_решітки, що відповідають найменуванню стовпця від продажів / замовлень, автоматично оновлюються в таблиці продажів / замовлень_решітки. Якщо вам потрібно додати варіант оплати, наприклад, вам знадобиться цей спостерігач, щоб додати поле до запиту, щоб дані можна було скопіювати у правильну таблицю. Для цього використовується спостерігач /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'
        //);
    }
}

Цей код заснований на прикладі http://www.ecomdev.org/2010/07/27/adding-order-attribute-to-orders-grid-in-magento-1-4-1.html

Сподіваємось, що приклад вище вирішує вашу проблему.


До жаль , я не був в змозі перевірити це , як я подорожував ... Це звучить трохи більш складним , що мій підхід (це працює і для нового порядку?)
Від

Спостерігач сітки обробляє зміни даних при кожній зміні, оскільки це нативне використання Magento, вам не потрібно створювати ніяких приєднань до інших таблиць, це прискорює запит на велику кількість замовлень (усі дані зберігаються у sales_flat_order_grid).
Володимир Керхофф

Коли я намагаюся використовувати це, я отримую помилку Попередження: Відсутній аргумент 2 для Varien_Db_Adapter_Pdo_Mysql :: quoteInto ()
Vaishal Patel

4

Спробуйте скористатися цими:

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

1
Це повинно було бути реально прийнято як відповідь для підходу спостерігачів ОП.
musicliftsme

2

Чи дійсно вам потрібен у вашому методі salesOrderGridCollectionLoadBeforeнаступний код $collection->addFilterToMap('store_id', 'main_table.store_id');? Якщо не видалити його, спробуйте наступне:

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

Вже пробував як :( Column('store_id');не доступна на core_block_abstract_prepare_layout_before (_prepareColumn () викликається після того, як так стовпець не існує в той час) addFilterToMapне робить це робота
Від

будь-яка ідея, чому addFilterToMap не працює?
Fra

Soory У мене не було занадто багато часу, щоб оглянути це останні дні. Можливо завтра. Просто ідея, тому що я трохи пам'ятаю причину, чому я сказав не використовувати addFilterToMap, - це те, як ви використовуєте, можливо, неправильні, параметри неправильні або не використовуються в добру хвилину. Це просто ідеї від спогадів.
Sylvain Rayé

2

Замість використання статичного імені стовпця можна використовувати метод нижче для всіх стовпців. Я можу зрозуміти, якщо використовувати відповідь mageUz, яка буде працювати для одного стовпця, і якщо ви перейдете на інший стовпець, можливо, ви отримаєте таку ж помилку. Отже нижче код дає вам рішення для всіх стовпців одночасно.

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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.