ปล่อยให้เข้าร่วมตารางในแบบสอบถามการรวบรวม


27

ฉันกำลังทำสิ่งต่อไปนี้เพื่อรับคำสั่งบางส่วนจากระบบเพื่อการส่งออก:

$orders = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('status', $statusToExport)
    ->addFieldToFilter('store_id', $this->processingStoreId)
    ->addFieldToFilter('updated_at', array('gteq' => date('Y-m-d H:i:s', $lastSyncTime)));

ฉันต้องเพิ่มบางอย่างที่มันไม่ส่งออกหากคำสั่งซื้อentity_idอยู่ในตารางที่กำหนดเองที่ฉันมี ถ้าฉันใช้ SQL ฉันจะทำ:

left join myTable as mt on main_table.entity_id = mt.entity_id
where mt.entity_id is null

แต่ฉันไม่แน่ใจว่าจะแก้ไขแบบสอบถามคอลเลกชันเพื่อทำสิ่งที่คล้ายกันได้อย่างไร

หมายเหตุ: ฉันลองแล้ว

$orders = $orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null")

แต่นี่เป็นการเปลี่ยนแปลงเพื่อให้เป็นแบบสอบถามและฉันต้องการให้คอลเลกชันการขาย / การสั่งซื้อคืน

ฉันรู้สึกว่าฉันขาดอะไรง่าย ๆ ...

แก้ไข

ตกลงฉันได้ลองสิ่งนี้แล้ว:

$orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null");

เมื่อฉันก้อง(string)$orders->getSelect()มันส่งกลับแบบสอบถามที่ฉันคาดหวังและไม่มีผลลัพธ์เมื่อฉันเรียกใช้ $ordersอย่างไรก็ตามยังคงมีรายการ ฉันคิดว่าการเข้าร่วมครั้งนี้มีวัตถุประสงค์เพื่อปรับเปลี่ยนคอลเล็กชันในจุดนี้หรือไม่

คำตอบ:


53

หากต้องการเปลี่ยนแบบสอบถามที่คุณสามารถทำได้

$collection->getSelect()->doWhateverYouWantWithSelectObject();
foreach($collection as $order) {} // order collection

แต่หากต้องการเข้าร่วมตารางคุณสามารถใช้ $collection->joinTable()

joinTableมีอยู่ใน Mage_Eav_Model_Entity_Collection เท่านั้นซึ่งหมายความว่า: ผลิตภัณฑ์หมวดหมู่คำสั่งซื้อใบแจ้งหนี้เครดิตเครดิตการจัดส่งสินค้าลูกค้า (ขอบคุณ @Fra สำหรับความคิดเห็น)

joinTable ()

แต่คอลเลคชั่นวีโอไอพีนั้นมีวิธีการที่joinTable()ใช้เวลา 45 นาทีในการคลำวิธีการใช้งาน เพื่อหลีกเลี่ยงปัญหานี้สำหรับคุณฉันแบ่งปัน

$productCollection->joinTable(
    array('bonus' => 'mycompany/bonus'), 'product_id=entity_id',
    array('bonus_id' => 'bonus_id')
);

พารามิเตอร์คือ:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. ตารางเป็นเรื่องง่ายมันเป็นnamespace/entityรูปแบบวีโอไอพีที่คุณใช้ในการกำหนดค่าโมเดลทรัพยากรและคอลเลกชันของคุณ คุณสามารถใช้อาร์เรย์ของรูปแบบarray('alias' => 'namespace/entity')
  2. การผูกหมายถึงคำสั่ง ON ใน SQL ของคุณ นี่คือส่วนที่ยากที่สุดและฉันจะอธิบายในรายละเอียดในภายหลัง มันเป็นสิ่งสำคัญที่จะต้องมีโต๊ะแบนของคุณก่อนและโต๊ะ EAV ของคุณหลังจากที่เครื่องหมายเท่ากับ อย่าใช้main_table.ก่อนแอตทริบิวต์ วีโอไอพีจะทำสิ่งนี้เพื่อคุณ เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง
  3. ทุ่งเป็นอาร์เรย์ Warning: Invalid argument supplied for foreach() in /var/www/magento-1.6.2.0/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php on line 775ถ้าคุณใช้สตริงแทนคุณได้รับนี้ คุณสามารถใช้อาร์เรย์ของรูปแบบarray('field1', 'field2', '...')หรือarray('alias' => 'field1', '...')
  4. สภาพเป็น ** WHERE ON เงื่อนไข ** ใน SQL
  5. joinType ฉันหวังว่าคุณจะรู้ว่ามันคืออะไร แต่คุณมีเพียงทางเลือกระหว่างซ้ายและด้านในapp/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

เพิ่มเติมในหัวข้อนี้


1
ขอบคุณสำหรับข้อมูลที่ดี จากจุดแรกของคุณไม่ควร$orders->getSelect() ->joinLeft(array("t1" => $myTable), "main_table.entity_id = t1.entity_id", array("admin_field_id" => "t1.id")) ->where("t1.id is null")แยกรายการออกจากรายการปัจจุบันของฉัน
webnoob

ฉันคิดว่าคุณแก้ไขคอลเลกชันหลังจากโหลด เพียงเชื่อมต่อสคริปต์ของคุณกับ xdebug และตรวจสอบธง isLoaded ภายในโมเดล
Fabian Blechschmidt

2
มูลค่าที่ระบุว่าวิธีการ joinTable จะใช้ได้เฉพาะ Mage_Eav_Model_Entity_Collection
Fra

1

ฉันพบเหตุผลสำหรับสิ่งนี้

ฉันต้องการนับจำนวนก่อนที่ฉันจะใช้การเข้าร่วมทางซ้ายดังนั้นฉันจึงเพิ่ม

$totalOrderCount = count($orders);

อย่างไรก็ตามสิ่งนี้ทำให้คอลเลกชันโหลดซึ่งหมายความว่ามันไม่สนใจการเข้าร่วมด้านซ้ายที่ฉันทำต่อไป ในขณะที่การดีบักการดู var _isCollectionLoadedเป็นคำแนะนำที่ดีโดย Fabian

ตอนนี้ฉันกำลังทำสิ่งนี้แทนเพื่อรับจำนวนคอลเล็กชัน:

$countOrdersObjs = clone $orders;
$totalOrderCount = count($countOrdersObjs);
unset($countOrdersObjs);

สิ่งนี้ทำให้ฉันสามารถนับผลลัพธ์ได้โดยไม่โหลด$ordersคอลเลกชัน

หมายเหตุ: โปรดใช้ upvotes ใด ๆ กับโพสต์ Fabians ข้างต้นในขณะที่เขาแนะนำฉันเกี่ยวกับเรื่องนี้ แต่ฉันรู้สึกว่าวิธีการแก้ปัญหาที่รับประกันมันเป็นคำตอบของตัวเอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.