2

我正在为拥有基于 Magento 的商店的客户工作。它塞满了产品,但所说的产品的名称有点乱。他没有坚持一种命名约定,而是多年来使用不同的约定。因此,每当他使用“管理”->“管理产品”部分中的“名称”过滤器查找某些内容时,结果仍有很多不足之处。

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

任何提示将不胜感激。干杯!

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

数组 ([like] => Zend_Db_Expr Object([_expression:protected] => '%search term%' ))

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

4

4 回答 4

3

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

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

事实并非如此。Magento 不执行OR,但LIKE在这种情况下搜索。

这也解释了为什么

LIKE name = '%word1 word2 word3%'

通常从不* 可以匹配 a 的结果集

LIKE name = '%word1 word3%'

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

祝你好运!


* 除了word2 == word3, 当然

于 2012-08-15T21:42:41.843 回答
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).")");
    }

代码没有经过测试,例子很简单,但我想你理解了这个想法;)祝你好运!

于 2012-09-06T22:15:44.997 回答
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”搜索过滤器,您将获得正确的结果。我愿意接受建议,这可能不是最好的方法。我会在正确测试后更新。干杯!

9 月 6 日更新:嗯,经过一些现场测试,结果很好,正是我想要的。似乎也没有负面的性能影响。

有趣的事实是,这个小修改适用于在管理界面中有产品网格的每个地方进行过滤(例如,当手动创建新订单并单击添加产品时,或在管理类别 -> 任何类别中 - > 类别产品选项卡)

9 月 6 日更新 2:有一个问题。如果您在订单网格中并尝试​​按状态过滤,则会引发错误。我需要使此过滤器仅适用于名称字段。有任何想法吗?

9 月 6 日更新 3:我将脚本修改为仅适用于产品网格的名称字段。现在,通过可见性过滤产品或按状态排序等没有冲突。

于 2012-09-01T12:52:48.150 回答
0

要做通配符 % 搜索给定的列,如果你可以覆盖 core 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]);
        }
    }
}
于 2019-03-15T06:59:20.247 回答