Magento:admin - 产品搜索过滤器

时间:2012-08-15 13:03:07

标签: magento admin filtering

我正在为拥有基于Magento的商店的客户工作。它充满了产品,但所述产品的名称有点凌乱。他没有坚持一个命名惯例,但多年来一直使用不同的惯例。因此,每当他使用Admin中的Name过滤器查找某些内容时 - >管理产品部分,结果有很多不足之处。

所以我想知道是否有办法使滤波算法更加宽松,特别是在字顺序方面。因为如果您的产品名称为“ word1 word2 word3 ”,并且您搜索“ word1 word3 ”,则产品不会出现在结果中。

任何暗示都将受到赞赏。干杯!

8月28日更新:我的搜索引导我进入类* Mage_Adminhtml_Block_Widget_Grid *,更确切地说是其受保护的方法* _addColumnFilterToCollection()*。在这里你有 $ cond 变量,如果你打印出来它会给你这样的东西:

  

Array([like] => Zend_Db_Expr Object([_ expression:protected] =>'%search term%'))

这里,如果我可以拦截该搜索词,并在提交给* Zend_Db_Expr *对象之前将其变为'%search%term%',我可能会解决我的问题。那么,有什么想法吗?

4 个答案:

答案 0 :(得分:3)

这需要编写具有一定复杂性的自定义模块。

期望,word1 word3的过滤应该至少返回匹配的子集,过滤word1 word2 word3确实会返回,这是基于Magento执行的错误假设OR搜索此网格过滤器。

这是的情况。在这种情况下,Magento不执行OR,但LIKE搜索。

这也解释了为什么结果集

LIKE name = '%word1 word2 word3%'

通常从不 *可以匹配

的结果集
LIKE name = '%word1 word3%'

我认为Mage_Adminhtml_Block_Catalog_Product_Grid::_prepareCollection()是您的代码需要覆盖的最小值,以帮助您入门。

祝你好运!


*除了word2 == word3,当然还有

答案 1 :(得分:2)

您可以将'filter_condition_callback'添加到Magento中的任何网格。为Magento产品网格创建重写并将此参数添加到“名称”字段。像

$this->addColumn('name',
            array(
                'header'=> Mage::helper('catalog')->__('Name'),
                'index' => 'name',
                'filter_condition_callback' => array($this, 'filter_name_callback'),
        ));

然后在同一个类中确定filter_name_callback方法。 像这样:

protected function filter_name_callback($collection, $column)
    {
        $names = $column->getFilter()->getValue();
        $namesArray = explode(' ', $names);
        $cond = array();
        foreach ($namesArray as $item)
        {
            $cond[] = 'main_table.name LIKe %'.$item.'%';
        }

        $collection->getSelect()->where("(".implode(' OR ', $cond).")");
    }

代码未经过测试,示例很简单,但我认为您理解这个想法;)祝您好运!

答案 2 :(得分:1)

好的,这是这个问题的解决方案。请注意,我没有对此进行太多测试,只是在我当地的测试magento上。所以可能会出现问题。

我们的工作类是Mage_Adminhtml_Block_Widget_Grid,位于'app / code / core / Mage / Adminhtml / Block / Widget / Grid.php'中。你应该在'app / code / local / Mage / Adminhtml / Block / Widget / Grid.php'中复制这个文件,以免覆盖核心类。

现在,在该文件中转到名为_addColumnFilterToCollection的函数。在这里,删除'} else {'语句中的所有内容并替换为:

$cond = $column->getFilter()->getCondition();
if ($field == "name" && isset($cond)) {
$filterOrig = $cond['like'];
$filterReplaced = str_replace(" ", "%", $filterOrig);
$newZendDbExpr = new Zend_Db_Expr($filterReplaced);
$modifCond = array('like'=>$newZendDbExpr);
$this->getCollection()->addFieldToFilter($field , $modifCond);
} else if ($field && isset($cond)) {
$this->getCollection()->addFieldToFilter($field , $cond);
}

'$ cond'变量是这里的关键。如果你打印它,你会得到类似的东西:

Array([like] => Zend_Db_Expr Object([_expression:protected] => '%filter term%'));

该代码段基本上拦截传递给Zend_Db_Expr对象的过滤器术语,将其传递给str_replace()以用'%'通配符替换任何空格,然后将其发送回对象。

现在,如果您的产品名称为'word1 word2 word3',并按术语'word1 word3'进行搜索过滤,您将获得正确的结果。我愿意接受建议,这可能不是最好的方法。我会在正确测试之后更新。干杯!

SEP 06更新:嗯,经过一些实时测试,结果很好,正是我想要的。似乎也没有负面的性能影响。

有趣的是,这个小修改适用于在管理界面中有产品网格的每个地方进行过滤(例如,手动创建新订单并单击添加产品或在管理类别中 - > ;无论什么类别 - >类别产品标签)

SEP 06更新2 :存在问题。如果您在Orders网格中并尝试​​按状态过滤,则会引发错误。我需要使此过滤器仅适用于Name字段。有什么想法吗?

SEP 06更新3 :我修改了脚本以仅应用于产品网格的名称字段。现在,按可见性或按状态等顺序与过滤器产品没有冲突。

答案 3 :(得分:0)

要对通配符%搜索给定的列,并且如果可以覆盖核心Grid.php,则可以在网格类中执行以下操作:

protected function _prepareColumns()
{
    parent::_prepareColumns();   

    // assuming the column is 'name' for product name in the product grid
    $this->getColumn('name')->setFilterConditionCallback([$this, 'allowWildcardInFilter']);
    ...
}

/**
 * Allow wildcard % in column search
 */
public function allowWildcardInFilter($collection, $column)
{
    if ($value = $column->getFilter()->getValue()) {
        if ($field = $column->getFilterIndex() ? $column->getFilterIndex() : $column->getIndex()) {
            /**
             * @var $helper Mage_Core_Model_Resource_Helper_Mysql4
             */
            $helper = Mage::getResourceHelper('core');
            $likeExpression = $helper->addLikeEscape($value, [
                'position' => 'any',
                'allow_string_mask' => true
            ]);
            $collection->addFieldToFilter($field, ['like' => $likeExpression]);
        }
    }
}