2

我需要重新组织产品列表类别页面。我的产品中有一个date_field属性需要遵循此排名:

  • date_field >= today的产品首先出现
  • 将其合并到date_field < 今天的产品

因此,我使用以下代码为catalog_block_product_list_collection调度程序创建了一个观察者:

$original_collection = clone $observer->getEvent()->getCollection();

$observer->getEvent()->getCollection()
                ->addAttributeToFilter('data_inicio', array('gteq' => date('Y-m-d')));

$collection2 = $original_collection
                ->addAttributeToFilter('data_inicio', array('lt' => date('Y-m-d')));

//and after I will merge both collections by adding each item from $collection2 into $observer

但是当在$collection2上再次应用相同的过滤器时,它会引发以下错误:

您不能多次定义相关名称“_table_data_inicio_default”

只有过滤器的第一部分工作正常。有没有更好的方法来做到这一点?

4

2 回答 2

3

PHP 克隆的问题在于它不是深度克隆,因此某些资源是共享的,因此您看到的名称冲突。我发现最好的做法是在 SQL 中做尽可能多的工作,然后这些小问题很少出现。

$collection = $observer->getEvent()->getCollection();
// store old ordering
$orderBys = $collection->getSelect()->getPart(Zend_Db_Select::ORDER)
$collection->getSelect()->reset(Zend_Db_Select::ORDER);

// set first order part
$collection->addExpressionAttributeToSelect(
               'future',
               'IF({{data_inicio}}>="' . date('Y-m-d') . '",1,0)',
               'data_inicio')
           ->addAttributeToSort('future', 'desc');

// reinstate old ordering afterwards
foreach ($orderBys as $orderBy) {
    $collection->getSelect()
        ->order(is_array($orderBy) ? implode(' ', $orderBy) : $orderBy);
}

在这里,创建了一个表达式future来比较日期,然后首先使用今天或更大的行进行排序。它不是按 排序的data_inicio。它可能会覆盖任何默认排序,并且 - 我尚未对此进行测试 - 可能会在用户排序之后应用。

于 2012-09-27T19:38:56.780 回答
0

- >addExpressionAttributeToSelect()是诀窍!我在排序时遇到了一些问题,因为在观察者之前还有其他字段被排序。所以我重新设置了它们...

我的代码:

$observer->getEvent()->getCollection()
    ->addExpressionAttributeToSelect(
        'future',
        'IF({{data_inicio}}="' . date('Y-m-d') . '",2,  IF({{data_inicio}}>="' . date('Y-m-d') . '",1,0))',
        'data_inicio')
    ->getSelect()->reset('order')->order(array('future desc', 'data_inicio asc'));

我还在里面添加了另一个 IF 并添加了第二列进行排序。

再次感谢@clockworkgeek。

于 2012-09-27T20:58:40.417 回答