将列添加到网格(观察者) - 列中的“ store_id”列中的子句是模棱两可的问题
-
16-10-2019 - |
题
我正在使用观察者方法向订单网格添加一列:
- 在活动中 - >
sales_order_grid_collection_load_before
我在收藏中添加了一个加入 - 在活动中 - >
core_block_abstract_prepare_layout_before
我在网格中添加了一列
编辑 更多信息:
在事件(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列,但是 通过观察者所以问题是我该怎么做 即时 ?
不覆盖块 班级 ? (否则观察者的方法是没有用的)
解决方案
让我们在我之前提到的其他解决方案上再次尝试一下:-),我已经构建了完整的扩展程序,以向您展示如何将字段添加到网格表中。之后,您只需要一个布局更新文件即可将列添加到您的订单网格页面。
我打电话给扩展名示例_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/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)以外的表中创建额外的列时,才需要最后一个文件。销售/订单中的所有字段匹配销售/订单中的列名称的所有字段将在sales/order_grid表中自动更新。例如,如果需要添加付款选项,则需要此观察者将字段添加到查询中,以便可以将数据复制到正确的表格中。用于此的观察者在 /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'
//);
}
}
希望上面的示例能够解决您的问题。
其他提示
尝试使用这些:
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);
}
}
您真的需要您的方法吗 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'));
}
}
而不是使用静态列名称,您可以将下面的方法用于所有列。我可以理解是否使用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);
}