Có thể lặp lại các bộ sưu tập Magento với phân trang nguyên bản không?


21

Điều tôi muốn nói là - có một cách để làm:

$collection = $model->getCollection();
foreach ($collection as $item) { 
    $item->doStuff();
}

Theo cách mà ngay cả khi bộ sưu tập có 100 nghìn hàng, nó sẽ chỉ tải một trang hàng tại một thời điểm từ MySQL và phân trang chúng một cách kỳ diệu cho bạn đằng sau hậu trường.

Từ việc nhìn vào Varien_Data_Collection_Db::load()có vẻ như không thể, nhưng chỉ muốn kiểm tra. Điều này có vẻ như một cái gì đó nên là một nhu cầu phổ biến.

Câu trả lời:


18

Bạn thực sự nên sử dụng

Mage::getSingleton('core/resource_iterator')

cho mục đích này, vì nó tồn tại hoàn toàn vì lý do hiệu suất mà bạn đề cập.

Mặt khác, bạn có thể sử dụng một giải pháp ít thanh lịch hơn bằng cách sử dụng vòng lặp với setPageSize- có một ví dụ hay ở đây, /programming/3786826/how-to-loop-a-magento-collection


1
Bạn, quý ngài, một quý ông, và một học giả.
kalenjordan

+1 setPageSizevì nó là ngữ nghĩa.
philwinkle

Một điều khác mà tôi nhận ra là core/resource_iteratorgiải pháp thực sự không phân trang truy vấn mysql. Nó tải toàn bộ tập kết quả cùng một lúc, nhưng sau đó nó cung cấp cho bạn một hàng tại một thời điểm để xử lý mã PHP của bạn. Vì vậy, nó tránh được lỗi bộ nhớ trong PHP, nhưng tại một số điểm, nó sẽ kích hoạt kích thước gói tối đa mysql, nếu tập kết quả là rất lớn. Tôi nghĩ rằng tôi sẽ thử và xây dựng một resource_iterator chunked trừu tượng bằng cách sử dụngsetPageSize()
kalenjordan

Vâng, tôi loại bỏ rằng theo đuổi các điểm mwoar! Nó thực sự nhằm mục đích tải sản phẩm duy nhất so với một bộ sưu tập phân trang. Nhưng nó sẽ phục vụ như là một cơ sở để xây dựng trên.
Ben Lessani - Sonassi

Tôi đã triển khai một trình vòng lặp theo đợt chung chung, theo đó các truy vấn tới MySQL nhưng cũng cung cấp một cuộc gọi lại mục bộ sưu tập riêng lẻ. Tò mò những gì bạn nghĩ: gist.github.com/kalenjordan/5483065
kalenjordan

5

Tôi đồng ý với Ben Lessani rằng bạn nên sử dụng core/iteratormô hình tài nguyên để tải các bộ sưu tập lớn một hàng mỗi lần nếu có thể .

Tuy nhiên, có những hạn chế. Như đã giải thích trong " addAttributionToSelect không hoạt động với core / resource_iterator? ", Nó không hoạt động tốt với các mô hình EAV nếu bạn cần bao gồm các giá trị từ các bảng giá trị thuộc tính.

Và ví dụ được liên kết từ StackOverflow thực sự không tốt vì nó lặp lại cùng một truy vấn với các LIMITbiểu thức khác nhau . Đối với các truy vấn phức tạp, đây có thể là một vấn đề về hiệu năng, nhưng thậm chí quan trọng hơn, bạn sẽ nhận được các bản sao nếu các hàng mới được thêm vào giữa.

Một cách tốt hơn để xử lý các bộ sưu tập trong các khối là trước tiên tải tất cả các id, sau đó sử dụng các id này làm bộ lọc cho bộ sưu tập phân trang thực tế.

Ví dụ đơn giản cho các sản phẩm:

$ids = Mage::getModel('catalog/product')
    ->getCollection()
    ->getAllIds();

$page = 1;
do {
    $collection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addIdFilter($ids)
        ->setPageSize(100)
        ->setCurPage($page);

    $results = $collection->load();

    // do stuff ......

    $page++;

} while ($results->count());
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.