Un peu de contexte pour cela. Je souhaite étendre la fonction d'exportation de commande client (via la grille) pour avoir plus de colonnes. J'ai créé un module qui ajoute une nouvelle grille pour l'exportation et aussi un nouveau modèle de collection qui étend l'original. Cela utilise la fonction _beforeLoad () afin que je puisse rejoindre les tables dont j'ai besoin.
Le problème que j'ai est que lorsque les filtres de la grille sont ajoutés (increment_id, date de commande, etc.), la clause where que cela ajoute ne préfixe pas la table et je rencontre des problèmes avec les noms de colonnes ambigus. Par exemple, sur increment_id, j'ai le problème dans la clause where:
SELECT `main_table`.*, `sales`.`total_qty_ordered`, `sales`.`entity_id` AS `order_id`, `sagepay`.`vendor_tx_code` FROM `sales_flat_order_grid` AS `main_table`
LEFT JOIN `sales_flat_order` AS `sales` ON main_table.increment_id = sales.increment_id
LEFT JOIN `sagepaysuite_transaction` AS `sagepay` ON order_id = sagepay.order_id WHERE (increment_id LIKE '%100000261%') GROUP BY `main_table`.`entity_id`
Cette clause where est ajoutée avant de faire les jointures aux autres tables de la fonction _addColumnFilterToCollection ()
protected function _addColumnFilterToCollection($column)
{
if ($this->getCollection()) {
$field = ( $column->getFilterIndex() ) ? $column->getFilterIndex() : $column->getIndex();
if ($column->getFilterConditionCallback()) {
call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);
} else {
$cond = $column->getFilter()->getCondition();
if ($field && isset($cond)) {
// Filter added at this point
$this->getCollection()->addFieldToFilter($field , $cond);
}
}
}
return $this;
}
Comme un bref test, j'ai changé la ligne en
$this->getCollection()->addFieldToFilter('main_table.' . $field , $cond);
et cela a fonctionné, mais cela ne semble pas être une excellente façon de le faire.
Mon code dans _beforeLoad () est
protected function _beforeLoad()
{
// Join the sales_flat_order table to get order_id and and total_qty_ordered
$this->getSelect()->joinLeft(array('sales' => $this->getTable('sales/order')),
'main_table.increment_id = sales.increment_id',
array('total_qty_ordered' => 'sales.total_qty_ordered',
'order_id' => 'sales.entity_id'));
// Join the SagePay transaction table to get vendor_tx_code
$this->getSelect()->joinLeft(array('sagepay' => $this->getTable('sagepaysuite2/sagepaysuite_transaction')),
'order_id = sagepay.order_id',
array('vendor_tx_code' => 'vendor_tx_code'));
$this->getSelect()->group('main_table.entity_id');
parent::_beforeLoad();
}
Je dois utiliser increment_id pour rejoindre la table de grille de commande client et la table de transaction SagePay car c'est le seul ID commun que je puisse voir.
Fondamentalement, je me demande quelle est la meilleure approche pour y remédier. Je pourrais probablement m'en tirer en faisant le changement que j'ai mentionné ci-dessus, mais cela ne me semble pas correct. Y a-t-il quelque chose que je puisse changer dans mes déclarations de jointure?
Merci.
Réponses:
Vous pouvez facilement résoudre toute condition ambiguë où en utilisant la méthode de collecte suivante:
addFilterToMap($filterName, $alias, $group = 'fields')
$filter
- c'est le nom du filtre qui est utilisé dans laaddFieldToFilter()
méthode, pour votre cas c'estincrement_id
$alias
- c'est le nom complet de la colonne qui est associée au filtre, pour vous c'est le casmain_table.increment_id
.$group
- était destiné à être une carte pour tout type d'informations dans la collection, mais pour l'instant, il n'est utilisé que dans les filtres, vous pouvez donc omettre cet argument.De plus, je ne pense pas que beforeLoad soit le bon endroit pour placer vos jointures, sauf si vous observez un événement. Dans votre cas, il est préférable de le déplacer dans la
_initSelect()
méthode en appelant avantparent::_initSelect()
. Vous pouvez appeler laaddFilterToMap()
méthode à l'intérieur de votre_initSelect()
méthode pour résoudre les conflits de jointure, comme ceci:la source
_initSelect
n'est exécuté qu'une seule fois tout le temps,_beforeLoad
peut être appelé plus d'une fois, car vous pouvezload()
collecter plusieurs fois si vous réinitialisez son état.$collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');