あいまいな列名を持つwhere句の競合


28

このための少しのコンテキスト。(グリッドを介して)注文のエクスポート機能を拡張して、列を増やしたい。エクスポート用の新しいグリッドと、元のモデルを拡張する新しいコレクションモデルを追加するモジュールを作成しました。これは_beforeLoad()関数を使用するため、必要なテーブルを結合できます。

私が抱えている問題は、グリッドからフィルターが追加されると(increment_id、注文日など)、これによって追加されるwhere句がテーブルの前に付かないため、あいまいな列名の問題が発生することです。たとえば、increment_idでは、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`

このwhere句は、_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;
    }

簡単なテストとして、行を

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

これは機能しましたが、それを行うのに最適な方法ではありません。

_beforeLoad()の私のコードは

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

私が見ることができる唯一の共通IDであるため、私はincrement_idを使用して販売注文グリッドテーブルとSagePayトランザクションテーブルを結合する必要があります。

基本的に、私はこれに取り組むための最良のアプローチは何だろうと思っています。上記の変更を行うことでおそらく逃げることができますが、それは正しいとは感じません。結合ステートメントで変更できるものはありますか?

ありがとう。


1
どのようにテーブルに参加しましたか?magentoはジョイントテーブルを記録し、通常はすべてのプレフィックスを追加するため、Zend_Db_Selectモデルでの作業はお勧めできません。私は多分それは助け、参加についてのブログ記事を書いた:blog.fabian-blechschmidt.de/articles/...
ファビアンBlechschmidt

回答いただきありがとうございます。それについて読みます。joinTable()を使用しようとしましたが、コレクションモデルでは使用できませんでした。
ポール

回答:


52

次の収集方法を使用すると、あいまいなwhere条件を簡単に解決できます。

  • addFilterToMap($filterName, $alias, $group = 'fields')
    • $filter- addFieldToFilter()メソッドで使用されるフィルターの名前です。あなたの場合はincrement_id
    • $alias-フィルターに関連付けられている列のフルネームですmain_table.increment_id
    • $group -コレクション内のあらゆる種類の情報のマップにすることを目的としていましたが、現在はフィルターでのみ使用されているため、この引数は省略できます。

また、イベントを監視している場合を除き、beforeLoadが結合を配置するのに適切な場所だとは思いません。あなたの場合、_initSelect()beforeを呼び出してメソッドに移動することをお勧めしparent::_initSelect()ます。次のように、addFilterToMap()メソッド内でmethod を呼び出して_initSelect()、結合の競合を解決できます。

$this->addFilterToMap('increment_id', 'main_table.increment_id');

興味深いことに、なぜ_initSelect()で結合を行う方が良いのでしょうか?
ポール

@Paul _initSelectは常に一度だけ実行され、状態をリセットすると複数回収集_beforeLoadできるため、複数回呼び出すことができload()ます。
イヴァンチェプルニー

@Paulも、_beforeLoadを2回呼び出すことができるため、2回目の呼び出しでZend_Db_Selectから致命的なエラーを受け取ります。
イワンチェプルニー

2
私はこのようなことをしました: $collection = Mage::getModel("education/ticket") ->getCollection() ->addFilterToMap('updated_at', 'main_table.updated_at') ->addFilterToMap('created_at', 'main_table.created_at');
FosAvance

@IvanChepurnyi、天才です。これは、Magento 1アーキテクトとして優れていることを反映しています
Amit Bera
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.