Как выбрать определенные поля с псевдонимами, используя joinTable или joinField в Magento - PullRequest
9 голосов
/ 16 октября 2010

Я хочу предварительно отфильтровать * данные в сетке счетов, видимой в админ-панели Magento.

Здесь - это вопрос, который я задавал ранее, и этот вопрос связан с представленным для этого решением, поэтому он может послужить хорошим объяснением.

Итак,Я изменяю метод Mage_Adminhtml_Block_Sales_Invoice_Grid :: _ prepareCollection, чтобы он сначала выбирал клиента, на которого ссылался зарегистрированный администратор.Затем он будет получать заказы от этих клиентов (в идеале только идентификаторы заказов). Затем присоедините эту коллекцию к sales / order_invoice_grid , чтобы получить счета для этого администратора.

На основеВ последнем ответе и используя эти документы, я попытался объединить эту информацию тремя способами: (Пример кода 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) с таким же идентификатором "1" уже существует

Мне нужны только идентификаторы заказа, чтобы я мог получить связанные счета, что говорит о том, что я также могу использовать функцию joinField, которую я попробовал следующим образом:

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

Но это дает мне следующую ошибку:

Item (Mage_Customer_Model_Customer) с тем же идентификатором "1"уже существует

Я ищу решение, которое объединяет счета клиентов->


Под предварительным фильтром я подразумеваю, что данные, перечисленные в сетке, фильтруются еще дочто-нибудь представлено в сетке.


Хорошо, теперь мой код выглядит так:

$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 ]

9 голосов
/ 17 октября 2010

Вот итог моего тестового скрипта. Чтобы поместить его в файл в корне Magento и ввести его URL-адрес непосредственно в браузере, он не обрабатывается контроллерами Magento. Это хороший способ экспериментировать, поскольку на него не влияют другие модули, макеты страниц и т. Д.

<code><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());

?>

Как и в случае с вашим предыдущим вопросом, я решил сбросить начальные столбцы, потому что я не верю в работу базы данных с большей, чем необходимо Тем не менее, это не существенно, тест все равно будет успешным без него.

Если это не сработает в вашей установке, тогда мы должны рассмотреть, какое это внешнее влияние может быть.

2 голосов
/ 18 октября 2010

Я наконец-то добился этого, перейдя по счету-> заказ-> покупатель, как предложила Анда Б. Я просто вставляю свое решение в качестве ссылки, но буду использовать это решение из clockworkgeek , так как оно кажется намного чище. И мое решение все еще нужно сделать более чистым, получая 'id' eav_attribute (agent_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;
2 голосов
/ 16 октября 2010

Ошибка " Объединенное поле с этим псевдонимом (0) уже объявлено. " происходит, потому что оно использует ключи массива в качестве псевдонимов.Поскольку у вас есть два joinTable() вызова, каждый с массивом, он пытается использовать индекс с нулями для обоих и, очевидно, имеет конфликт.
Так что вместо

array('entity_id as order_entity_id')

try

array('entity_id' => 'order_entity_id')

чтобы избежать конфликта.

1 голос
/ 25 сентября 2013

Самый простой способ, который я узнал на форуме 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);
1 голос
/ 16 октября 2010

Это выдает эту ошибку «Элемент (Mage_Customer_Model_Customer) с тем же идентификатором« 1 »уже существует», поскольку клиент может иметь несколько заказов и, следовательно, может иметь две или более записей с одним и тем же идентификатором клиента - вы создаете коллекцию клиенты, и вы должны иметь уникальные записи в коллекции. Вы должны начать с счетов и присоединиться к ним с клиентами.

...