如何使用Magento中的joinTable或joinField选择具有别名的特定字段

时间:2010-10-16 15:19:46

标签: magento e-commerce

我想在Magento管理面板中可见的发票网格中预过滤*数据。

Here是我之前提出的一个问题,这个问题与为此提出的解决方案有关,因此它可能是一个很好的解释。

所以,我正在修改Mage_Adminhtml_Block_Sales_Invoice_Grid :: _ prepareCollection方法,以便它首先获取登录管理员引用的客户。然后它将从这些客户获取订单 - 理想情况下只有订单ID - 然后将此集合加入 sales / order_invoice_grid ,以便为此管理员列出发票。

根据最后一个答案并使用these文档,以下是我尝试加入此信息的3种方式:(代码示例1)

$collection = Mage::getResourceModel('customer/customer_collection');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('*'));
$collection->joinTable('sales/invoice_grid', 'order_id=main_table.entity_id', array('*'));

当我执行上述操作时,我看到以下错误:

A joint field with this alias (0) is already declared.

#0 /var/www/magento/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php(706): Mage::exception('Mage_Eav', 'A joint field w...')
#1 /var/www/magento/app/code/local/Myproject/Adminhtml/Block/Sales/Invoice/Grid.php(41): Mage_Eav_Model_Entity_Collection_Abstract->joinTable('sales/invoice_g...', 'order_id=main_t...', Array)
#2 /var/www/magento/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(576): Myproject_Adminhtml_Block_Sales_Invoice_Grid->_prepareCollection()
#3 /var/www/magento/app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(582): Mage_Adminhtml_Block_Widget_Grid->_prepareGrid()

如果我删除对joinTable的第二次调用,上面的代码可以正常工作,但这不是我想要的。

我尝试的另一种方法是使用此代码:

$collection = Mage::getResourceModel('customer/customer_collection');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('entity_id as order_entity_id'));
$collection->joinTable('sales/invoice_grid', 'order_id=main_table.entity_id', array('*'));

这里错误出现在第二行,我实际上试图将字段order.entity_id别名,以便它不与发票表entity_id冲突。但是会产生如下错误:

  

物品(Mage_Customer_Model_Customer)   具有相同ID“1”已存在

我只需要订单ID,以便我可以获得相关的发票,这表明我也可以使用joinField函数,我尝试如下:

$collection = Mage::getResourceModel('customer/customer_collection');
$collection->joinField('order_entity_id', 'sales/order_grid', 'entity_id', 'customer_id=entity_id' , null, 'left');

但它给了我以下错误:

具有相同ID“1”的项目(Mage_Customer_Model_Customer)已存在

我正在寻找加入客户>发票的解决方案。


通过预过滤我的意思是即使在网格中出现任何内容之前,网格中列出的数据也会被过滤。


好的,现在我的代码看起来像:

$collection = 
Mage::getResourceModel('customer/customer_collection');
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('entity_id' => 'order_entity_id'));

我得到的错误是:

SELECT `e`.*, `sales_flat_order_grid`.`order_entity_id` AS `entity_id` FROM `customer_entity` AS `e`
 INNER JOIN `sales_flat_order_grid` ON (sales_flat_order_grid.customer_id=e.entity_id) WHERE (e.entity_type_id = '1') ORDER BY `e`.`created_at` desc, `e`.`created_at` desc LIMIT 20

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sales_flat_order_grid.order_entity_id' in 'field list'

5 个答案:

答案 0 :(得分:9)

以下是我的测试脚本的总数。要使用它放在Magento根目录下的文件中并直接在浏览器中输入它的URL,Magento的控制器不会处理它。这是一种很好的实验方法,因为它不受其他模块,页面布局等的影响。

<pre><?php

require 'app/Mage.php';
Mage::app();

$collection = Mage::getResourceModel('customer/customer_collection');
$collection->getSelect()->reset('columns');        
$collection->joinTable('sales/order_grid', 'customer_id=entity_id', array('order_entity_id' => 'entity_id'));
$collection->joinTable('sales/invoice_grid', 'order_id=order_entity_id', array('*'));

foreach ($collection as $invoice)
    print_r($invoice->debug());

?></pre>

与上一个问题一样,我选择重置初始列,因为我不相信为数据库提供超出必要的工作量。然而,它并不重要,没有它,测试仍然会成功。

如果这在您的安装中不起作用,那么我们需要考虑外部影响可能是什么。

答案 1 :(得分:2)

错误“已声明具有此别名(0)的联合字段。”因为它使用数组键作为别名而发生。由于你有两个joinTable()调用,每个都有一个数组,它试图使用两者的从零开始的索引,显然存在冲突。
而不是

array('entity_id as order_entity_id')

array('entity_id' => 'order_entity_id')

避免冲突。

答案 2 :(得分:2)

我终于通过发票 - &gt;订单 - &gt;客户实现了这一点,因为'Anda B'建议。我只是在这里粘贴我的解决方案作为参考,但将使用来自thisclockworkgeek解决方案,因为它看起来更清晰。而且我的解决方案仍然需要通过在运行时从数据库中获取eav_attribute(agent_id)的'id'而不是硬编码,如此粘贴在这里:

class Myproject_Adminhtml_Block_Sales_Invoice_Grid extends Mage_Adminhtml_Block_Sales_Invoice_Grid
{
    const AGENT_ID_ATTRIBUTE_ID = 118;

    protected function _prepareCollection()
    {

$collection = Mage::getResourceModel($this->_getCollectionClass());

        $collection->join('order_grid', 'order_id = order_grid.entity_id', array ('order_entity_id' => 'order_grid.entity_id'));
        $collection->getSelect()->join( 'customer_entity', 'customer_id = customer_entity.entity_id', array('customer_entity_id' => 'entity_id', 'email'));
        $collection->getSelect()->joinLeft( 'customer_entity_int', 'customer_entity_int.entity_id = customer_entity.entity_id AND attribute_id = ' . Myproject_Adminhtml_Block_Sales_Invoice_Grid::AGENT_ID_ATTRIBUTE_ID, 
                                        array('attribute_entity_id' => 'customer_entity_int.entity_id', 'attribute_id' , 'value'));

//Apply Desired Data Filters here

$this->setCollection($collection);

return $collection;

答案 3 :(得分:1)

它给你这个错误“具有相同id”1“的Item(Mage_Customer_Model_Customer)已经存在”因为一个客户可以有多个订单,因此可能有两个或多个具有相同客户ID的条目 - 你正在创建一个集合客户和您必须在集合中具有唯一条目。 您必须从发票开始并与客户一起加入。

答案 4 :(得分:1)

我从magento论坛发现的最简单的方法,

protected function _prepareCollection()
{
    $collection = Mage::getResourceModel('customer/customer_collection')

我们可以将自定义查询用作

$collection->getSelect()->columns(array('filename' => new Zend_Db_Expr ("(SELECT filename FROM cat WHERE customer_id =e.entity_id)")));

并且有效

$this->setCollection($collection);
var_dump($collection);