Còn lại tham gia một bảng trên một truy vấn bộ sưu tập


27

Tôi đang làm như sau để có được một số đơn đặt hàng ra khỏi hệ thống để xuất khẩu:

$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)));

Tôi cần thêm một cái gì đó vào nơi nó không xuất nếu đơn hàng entity_idnằm trong bảng tùy chỉnh mà tôi có. Nếu tôi đang sử dụng SQL, tôi sẽ làm:

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

Nhưng tôi không chắc chắn làm thế nào để sửa đổi truy vấn bộ sưu tập để làm một điều tương tự.

Lưu ý: Tôi đã thử

$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")

nhưng điều này thay đổi nó để nó là một truy vấn và tôi muốn bộ sưu tập bán hàng / đơn hàng được trả lại.

Tôi cảm thấy mình đang thiếu thứ gì đó đơn giản ...

CHỈNH SỬA

Ok, tôi đã thử điều này:

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

Khi tôi lặp lại, (string)$orders->getSelect()nó trả về truy vấn mà tôi mong đợi và không trả về kết quả nào khi tôi chạy nó. $ordersTuy nhiên, vẫn chứa các mặt hàng. Tôi nghĩ rằng tham gia này là để sửa đổi bộ sưu tập tại thời điểm này?

Câu trả lời:


53

Để thay đổi truy vấn bạn có thể làm

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

Nhưng để tham gia một bảng, bạn chỉ có thể sử dụng $collection->joinTable()

joinTablechỉ tồn tại trên Mage_Eav_Model_Entity_Collection, điều này có nghĩa là: sản phẩm, danh mục, đơn đặt hàng, hóa đơn, creditmemo, vận chuyển, khách hàng. (Cảm ơn @Fra đã bình luận)

tham gia ()

Nhưng các bộ sưu tập magento có một phương pháp joinTable()khiến tôi mất 45 phút để tìm hiểu cách sử dụng nó. Để tránh điều này cho bạn, tôi chia sẻ nó.

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

Các tham số là:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. Bảng rất dễ, nó là namespace/entityđịnh dạng magento , mà bạn sử dụng trong cấu hình, mô hình tài nguyên và bộ sưu tập của bạn. Bạn có thể sử dụng một mảng của định dạngarray('alias' => 'namespace/entity')
  2. Ràng buộc có nghĩa là, câu lệnh ON trong SQL của bạn. Đây là phần khó nhất và tôi sẽ giải thích chi tiết sau. Điều quan trọng là phải có bàn phẳng của bạn TRƯỚC và bảng EAV của bạn SAU dấu bằng. Đừng sử dụng main_table.trước thuộc tính. Magento sẽ làm điều này cho bạn. Thêm về điều này sau.
  3. Các lĩnh vực là một mảng . Nếu bạn sử dụng một chuỗi thay thế, bạn nhận được điều này : 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. Bạn có thể sử dụng một mảng của định dạng array('field1', 'field2', '...')hoặcarray('alias' => 'field1', '...')
  4. Điều kiện là một ** Ở ĐÂU Điều kiện ON ** trong SQL.
  5. tham gia Tôi hy vọng bạn biết nó là gì. Nhưng bạn chỉ có sự lựa chọn giữa TRÁI và INNER .app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

Thêm về chủ đề này


1
Cảm ơn thông tin tuyệt vời đó. Dựa trên điểm đầu tiên của bạn, không nên $orders->getSelect() ->joinLeft(array("t1" => $myTable), "main_table.entity_id = t1.entity_id", array("admin_field_id" => "t1.id")) ->where("t1.id is null")loại trừ các mục khỏi danh sách hiện tại của tôi?
webnoob

Tôi nghĩ bạn chỉnh sửa bộ sưu tập sau khi tải. chỉ cần nối vào tập lệnh của bạn với xdebug và kiểm tra cờ isLoaded bên trong mô hình
Fabian Blechschmidt

2
đáng để đề cập rằng phương thức tham gia chỉ có sẵn cho Mage_Eav_Model_Entity_Collection
Fra

1

Tôi tìm thấy lý do cho việc này.

Tôi muốn có một số giá trị trước khi tôi áp dụng tham gia bên trái vì vậy tôi đã thêm

$totalOrderCount = count($orders);

tuy nhiên điều này khiến cho bộ sưu tập tải, điều đó có nghĩa là nó đã bỏ qua việc tham gia bên trái mà tôi đang làm thêm. Trong khi gỡ lỗi, nhìn vào var _isCollectionLoadedlà một mẹo hay của Fabian.

Bây giờ tôi đang làm điều này thay vào đó để có được số lượng của bộ sưu tập:

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

Điều này cho phép tôi đếm kết quả mà không cần tải $ordersbộ sưu tập.

Lưu ý: Vui lòng áp dụng bất kỳ upvote nào cho bài viết của Fabians ở trên khi anh ấy hướng dẫn tôi về điều này nhưng tôi cảm thấy giải pháp được bảo đảm là câu trả lời của riêng mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.