Bagaimana cara mengkloning koleksi di Magento?

12

Saya memiliki satu koleksi dalam metode di mana saya ingin melakukan dua operasi berbeda pada koleksi ini. Jadi, saya ingin dua salinan terpisah dari koleksi yang sama, dan kemudian menetapkan satu dari dua koleksi untuk koleksi asli lagi dan mengembalikannya.

Untuk mempermudah ini, anggaplah saya memiliki koleksi objek yang disebut $collection.

Sekarang, saya mencobanya dengan kloning PHP karena saya tidak tahu apakah ada kloning koleksi Magento bawaan atau tidak.

$coll1 = clone $collection;
$coll2 = clone $collection;

Sekarang saya mencoba untuk melakukan operasi yang berbeda pada dua klon yang terpisah dari koleksi asli, semacamnya.

$coll1->getSelect()->where('some where condition');
$coll2->getSelect()->where('some different where condition');
if($coll1->count() == 0) {
    $collection = $coll2;
} else {
    $collection = $coll1;
}

Namun yang aneh adalah, kedua koleksi hasil kloning ini memiliki kedua kondisi yang ditentukan! Kondisi $ coll1 diterapkan ke $ coll2 bersama dengan kondisi $ coll2, dan sebaliknya.

Adakah yang tahu bagaimana mencapainya?

Terima kasih!

MagExt
sumber

Jawaban:

14

Penggunaan operator klon PHP, di mana kloning yang diinginkan, memerlukan kelas yang menyimpan objek pada properti menerapkan metode __clone untuk menyalin objek. Jika mereka tidak mendefinisikannya, properti pada kedua instance akan mereferensikan objek yang sama.

Magento tidak menerapkan __clone pada koleksi abstraknya, dan karenanya tidak mendukung kloning mendalam seperti yang Anda inginkan.

Saran saya adalah mencari cara lain untuk mencapai apa yang ingin Anda lakukan, karena mengkloning koleksi bisa sangat mahal.

Contoh yang Anda berikan (misalnya) dapat diubah untuk mengkloning pilih, memodifikasinya untuk memilih jumlah catatan yang akan dimuat dan kemudian berdasarkan hasil itu memodifikasi koleksi. Ini juga akan berkinerja lebih baik karena Anda tidak akan memuat koleksi dan menghitungnya hanya untuk menentukan yang mana yang akan digunakan.

EDIT: Berikut ini menunjukkan cara mengambil hitungan tanpa memuat atau benar-benar mengubah koleksi.

$collection = Mage::getModel(...)->getCollection();

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}
davidalger
sumber
Hanya detail kecil: Informasi tempat disimpan $collection->getSelect()dan tidak dalam koleksi itu sendiri.
Fabian Blechschmidt
Terima kasih atas jawabannya. Tetapi setelah menerapkan kondisi mana saja saya ingin tahu jumlah koleksi, dan berdasarkan hitungan itu hanya saya ingin memutuskan apakah menggunakan kondisi mana yang berbeda atau tidak. Bisakah Anda memposting beberapa cuplikan kode untuk lebih memahami bagaimana melakukannya?
MagExt
Jawaban diperbarui dengan contoh kode. Seperti @FabianBlechschmidt tunjukkan, di mana ada di pilih, di mana masalah spesifik Anda berasal karena itu tidak dikloning ketika objek koleksi dikloning dan keduanya akhirnya merujuk ke contoh objek yang sama dipilih.
davidalger
Terima kasih telah memperbarui. Saya belum mencoba ini karena saya sudah mendapatkan solusinya seperti itu saja.
MagExt
Sebenarnya jika ada masalah kloning koleksi, serialisasi dan unserialize dapat membantu dalam proses. Ada juga alternatif lain untuk mengkloning di PHP yang cukup baik. Tapi semuanya David benar ... pada dasarnya ketika Anda mengkloning objek Anda mengkloning pointer ke Objek bersarang yang melekat padanya, meskipun jawabannya tidak benar menyatakan masalah yang mendasarinya.
mprototype
1

Untuk memperluas jawaban @ davidalger, Anda dapat mengatur ulang pilihan jika Anda ingin melakukan operasi yang berbeda dari hitungan - seperti:

$select= $collection->getSelectCountSql()->reset();

$select
    ->from('newsletter_subscriber', array('some_column'))
    ->distinct();

Berhati-hatilah, ini dapat memiliki efek yang merugikan nantinya dalam proses karena ini memodifikasi koleksi.

Cara yang lebih baik adalah dengan mengkloning pilih entah bagaimana, tetapi salinan dangkal tidak akan memotongnya karena objek berisi tipe kompleks (Varien_Db_Select atau Zend_Db_Select memiliki __clonemetode).

Salah satu cara untuk menyiasatinya adalah dengan menyimpan data pilih, memodifikasinya, menjalankan kueri Anda, lalu memasukkan kembali data pilih asli.

Lihat di sini untuk contoh: https://ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

Erfan
sumber