Konflikte in der where-Klausel mit mehrdeutigen Spaltennamen

28

Ein bisschen Kontext dafür. Ich möchte die Exportfunktion für Kundenaufträge (über das Raster) um weitere Spalten erweitern. Ich habe ein Modul erstellt, das ein neues Raster für den Export und ein neues Sammlungsmodell hinzufügt, das das Original erweitert. Dabei wird die Funktion _beforeLoad () verwendet, damit ich die benötigten Tabellen verknüpfen kann.

Das Problem besteht darin, dass beim Hinzufügen der Filter aus dem Raster (increment_id, Bestelldatum usw.) die hinzugefügte where-Klausel der Tabelle kein Präfix hinzufügt und Probleme mit mehrdeutigen Spaltennamen auftreten. Auf increment_id habe ich beispielsweise das Problem in der where-Klausel:

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`

Diese where-Klausel wird hinzugefügt, bevor ich die Verknüpfungen mit den anderen Tabellen in der Funktion _addColumnFilterToCollection () durchführe

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

Als kurzen Test habe ich die Leitung auf geändert

$this->getCollection()->addFieldToFilter('main_table.' . $field , $cond);

und das hat funktioniert, aber es fühlt sich nicht gut an, es zu tun.

Mein Code in _beforeLoad () ist

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

Ich muss increment_id verwenden, um die Kundenauftragsgittertabelle und die SagePay-Transaktionstabelle zu verknüpfen, da dies die einzige häufig verwendete ID ist, die ich sehen kann.

Grundsätzlich frage ich mich, wie ich das am besten angehen kann. Ich könnte wahrscheinlich mit der oben erwähnten Änderung durchkommen, aber es fühlt sich nicht richtig an. Kann ich an meinen Join-Anweisungen etwas ändern?

Vielen Dank.

Paul
quelle
1
Wie bist du zu den Tischen gekommen? Das Arbeiten am Zend_Db_Select Modell ist eine schlechte Idee, da Magento die gemeinsamen Tabellen aufzeichnet und normalerweise alle Präfixe hinzufügt. Ich habe einen Blogartikel über das Beitreten geschrieben, vielleicht hilft es: blog.fabian-blechschmidt.de/articles/…
Fabian Blechschmidt
Vielen Dank für die Antwort, davon werde ich etwas lesen. Ich habe versucht, joinTable () zu verwenden, aber es war im Sammlungsmodell nicht verfügbar.
Paul

Antworten:

52

Mit der folgenden Erfassungsmethode können Sie mehrdeutige Where-Zustände auf einfache Weise beheben:

  • addFilterToMap($filterName, $alias, $group = 'fields')
    • $filter- Es ist der Name des Filters, der in der addFieldToFilter()Methode verwendet wird, in Ihrem Fallincrement_id
    • $alias- Es ist der vollständige Name der Spalte, die dem Filter zugeordnet ist, in Ihrem Fall main_table.increment_id.
    • $group - sollte eine Karte für jede Art von Informationen in der Sammlung sein, wird aber vorerst nur in Filtern verwendet, sodass Sie dieses Argument weglassen können.

Ich denke auch nicht, dass beforeLoad der richtige Ort ist, um Ihre Joins zu platzieren, es sei denn, Sie beobachten ein Ereignis. In Ihrem Fall ist es besser, die _initSelect()Methode mit vorherigem Aufruf zu verschieben parent::_initSelect(). Sie können eine addFilterToMap()Methode innerhalb Ihrer _initSelect()Methode aufrufen , um Join-Konflikte zu lösen:

$this->addFilterToMap('increment_id', 'main_table.increment_id');
Ivan Chepurnyi
quelle
Warum ist es aus Interesse besser, die Joins in _initSelect () auszuführen?
Paul
@Paul _initSelectwird immer nur einmal ausgeführt und _beforeLoadkann load()mehr als einmal aufgerufen werden, da Sie mehr als einmal sammeln können, wenn Sie den Status zurücksetzen.
Ivan Chepurnyi
@Paul auch, da _beforeLoad zweimal aufgerufen werden kann, erhalten Sie beim zweiten Aufruf einen schwerwiegenden Fehler von Zend_Db_Select.
Ivan Chepurnyi
2
Ich habe so etwas gemacht: $collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');
FosAvance
@ IvanChepurnyi, Sind genial. Es zeigt, dass Sie als Magento 1-Architekt ausgezeichnet sind
Amit Bera