如何在Magento中克隆收藏?


12

我有一个方法中的一个集合,我想对该集合执行两个不同的操作。因此,我想要同一集合的两个单独的副本,然后将两个集合之一再次分配给原始集合并返回它。

为简单起见,假设我有一个名为的对象集合$collection

现在,我正在尝试使用PHP克隆,因为我不知道是否有内置的Magento集合克隆。

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

现在,我试图对原始集合的这两个单独的克隆执行不同的操作,例如。

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

但是奇怪的是,这两个克隆的集合都分配了where条件!$ coll1条件与$ coll2的条件一起应用于$ coll2,反之亦然。

有谁知道如何实现这一目标?

谢谢!

Answers:


14

需要深度克隆的PHP克隆运算符的使用要求将对象存储在属性上的类实现__clone方法来复制对象。如果他们没有定义它,则两个实例上的属性将引用同一对象。

Magento并未在其集合摘要上实现__clone,因此不支持您想要的深度克隆。

我的建议是寻找其他方法来完成您想要的工作,因为克隆馆藏可能非常昂贵。

您提供的示例(例如)可以更改为克隆选择,将其修改为选择要加载的记录数,然后根据该结果修改集合。这也将更好地执行,因为您将不会加载集合并对其进行计数,而只是确定要使用哪个集合。

编辑:以下演示了如何获取计数而不加载或实际修改集合。

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

$count = $collection->getSelectCountSql();
$count->where('some where condition');
if ($count->query()->fetchColumn() == 0) {
    ...
} else {
    ...
}

只是一个小细节:位置的信息保存在$collection->getSelect()集合中,而不是保存在集合本身中。
Fabian Blechschmidt

感谢您的回答。但是,仅在应用where条件之后,我想知道集合计数,并且仅基于该计数,我想决定是否使用不同的where条件。您可以张贴一些代码片段以更好地了解该怎么做吗?
MagExt

用代码示例更新了答案。正如@FabianBlechschmidt指出的那样,select中的位置在哪里,这是您的特定问题的出处,因为在克隆收集对象时它不会被克隆,并且最终都引用同一个select对象实例。
davidalger

感谢您的更新。我还没有尝试过,因为我只有这样的解决方案。
MagExt

实际上,如果克隆集合存在问题,则序列化和反序列化在此过程中可能会有所帮助。还有其他在PHP中进行克隆的替代方法,它们相当不错。但总的来说,David是正确的……基本上,当您克隆对象时,您也正在克隆指向其附加的嵌套对象的指针,尽管他的回答没有正确说明潜在的问题。
mprototype

1

要扩展@davidalger的答案,如果要执行除计数之外的其他操作,可以重置选择-像这样:

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

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

但是请注意,由于这会修改集合,因此在此过程的后期可能会产生不利影响。

更好的方法是以某种方式克隆选择,但是浅拷贝不会将其剪切,因为对象包含复杂的类型(Varien_Db_Select和Zend_Db_Select具有__clone方法)。

解决此问题的一种方法是保存选择数据,对其进行修改,运行查询,然后放回原始选择数据。

参见此处的示例:https : //ka.lpe.sh/2013/05/23/magento-clone-collection-how-to-clone-collection-in-magento/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.