ความขัดแย้งในส่วนคำสั่งที่มีชื่อคอลัมน์ที่ไม่ชัดเจน


28

บริบทเล็กน้อยสำหรับสิ่งนี้ ฉันต้องการขยายฟังก์ชั่นการส่งออกคำสั่งขาย (ผ่านทางกริด) เพื่อให้มีคอลัมน์มากขึ้น ฉันได้สร้างโมดูลซึ่งเพิ่มกริดใหม่สำหรับการส่งออกและยังเป็นโมเดลคอลเลกชันใหม่ซึ่งขยายไปถึงต้นฉบับ นี่ใช้ฟังก์ชัน _beforeLoad () เพื่อให้ฉันสามารถเข้าร่วมตารางที่ฉันต้องการ

ปัญหาที่ฉันมีอยู่คือเมื่อเพิ่มตัวกรองจากกริด (the increment_id, วันที่สั่งซื้อ ฯลฯ ), ส่วนคำสั่งที่เพิ่มนี้ไม่ได้ขึ้นหน้าตารางและฉันได้รับปัญหาเกี่ยวกับชื่อคอลัมน์ที่ไม่ชัดเจน ตัวอย่างเช่นวันที่ 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`

ที่นี่มีการเพิ่มส่วนคำสั่งก่อนที่ฉันจะรวมเข้ากับตารางอื่น ๆ ในฟังก์ชัน _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();
}

ฉันต้องใช้ increment_id เพื่อเข้าร่วมตารางตารางคำสั่งขายและตารางธุรกรรม SagePay เนื่องจากเป็นรหัสทั่วไปเดียวที่ฉันเห็น

โดยทั่วไปฉันสงสัยว่าวิธีที่ดีที่สุดคือแก้ไขปัญหานี้ ฉันอาจจะได้รับไปกับการเปลี่ยนแปลงที่ฉันกล่าวถึงข้างต้น แต่มันก็ไม่ถูกต้อง มีสิ่งใดบ้างที่ฉันสามารถเปลี่ยนแปลงได้ในใบแจ้งยอดการเข้าร่วมของฉัน

ขอบคุณ


1
คุณเข้าร่วมตารางได้อย่างไร การทำงานกับโมเดล Zend_Db_Select เป็นแนวคิดที่ไม่ดีเพราะวีโอไอพีจะบันทึกตารางร่วมและเพิ่มส่วนนำหน้าทั้งหมดตามปกติ ฉันเขียนบทความบล็อกเกี่ยวกับการเข้าร่วมอาจช่วยได้: blog.fabian-blechschmidt.de/articles/ …
Fabian Blechschmidt

ขอบคุณสำหรับการตอบกลับฉันจะได้อ่าน ฉันพยายามใช้ joinTable () แต่ไม่มีในโมเดลการรวบรวม
พอล

คำตอบ:


52

คุณสามารถแก้ไขปัญหาที่คลุมเครือได้อย่างง่ายดายโดยใช้วิธีการรวบรวมต่อไปนี้:

  • addFilterToMap($filterName, $alias, $group = 'fields')
    • $filter- มันเป็นชื่อของตัวกรองที่ใช้ในaddFieldToFilter()วิธีการสำหรับกรณีของคุณมันเป็นincrement_id
    • $alias- main_table.increment_idมันเป็นชื่อเต็มของคอลัมน์ที่ถูกเชื่อมโยงกับตัวกรองสำหรับคุณกรณีที่เป็น
    • $group - ตั้งใจที่จะเป็นแผนที่สำหรับข้อมูลทุกประเภทในคอลเลกชัน แต่ตอนนี้มันถูกใช้ในตัวกรองเท่านั้นดังนั้นคุณจึงสามารถละเว้นอาร์กิวเมนต์นี้ได้

นอกจากนี้ฉันไม่คิดว่าก่อนโหลดเป็นสถานที่ที่เหมาะสมในการวางการเข้าร่วมของคุณเว้นแต่ว่าคุณกำลังสังเกตเหตุการณ์ ในกรณีของคุณมันจะดีกว่าที่จะย้ายเข้ามาด้วยวิธีโทรมาก่อน_initSelect() parent::_initSelect()คุณสามารถเรียกaddFilterToMap()วิธีการภายในวิธีการของคุณ_initSelect()สำหรับการแก้ไขข้อขัดแย้งการเข้าร่วมเช่นนี้:

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

ทำไมจึงเป็นการดีกว่าที่จะรวมใน _initSelect ()
พอล

@Paul _initSelectถูกดำเนินการเพียงครั้งเดียวตลอดเวลา_beforeLoadสามารถเรียกได้มากกว่าหนึ่งครั้งเนื่องจากคุณสามารถload()รวบรวมได้มากกว่าหนึ่งครั้งหากคุณรีเซ็ตสถานะ
Ivan Chepurnyi

@Paul เช่นกันเนื่องจาก _beforeLoad สามารถโทรได้สองครั้งคุณจะได้รับข้อผิดพลาดร้ายแรงจาก Zend_Db_Select เมื่อมีการโทรครั้งที่สอง
Ivan Chepurnyi

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.