西部数码主机 | 阿里云主机| 虚拟主机 | 服务器 | 返回乐道官网
当前位置: 主页 > php教程 > magento教程 >

用*s实现通过Magento后台网格进行搜索

时间:2017-01-07 11:00来源:未知 作者:好模板 点击:
为什么在Magento后台列里搜索某些值时不能使用索引?(例如order#) 当你的网站有几个管理员的时候,这篇简短的文章将非常有用。我在一个项目中有超过2000个有不同角色的管理员(这

为什么在Magento后台列里搜索某些值时不能使用索引?(例如order#)

当你的网站有几个管理员的时候,这篇简短的文章将非常有用。我在一个项目中有超过2000个有不同角色的管理员(这个数字还在增长)。你可以想像下当大量管理员在使用后台时是有多慢,特别是他们在搜索或者为数据排序时。

2000名管理员对Magento来说是个大数字吗?取决于他们如何使用后台部分,但是他们中的大部分要排列东西,搜索些有时他们并不需要的东西。

在实现新功能前,我们做了一次测试。试图在Magento后台寻找你的销售订单网格中的#: 10。记住有多少搜索结果,花了多长时间。

为什么通过Magento网格搜索花费如此大?

因为当你在搜索语句两侧都使用Like语句时MySQL服务不能使用索引。记住MySQL(innodb)有B-Tree索引。

一个例子,当你想要找出所有使用gmail作为邮箱的客户。你可以搜索Magento后台客户网格的邮箱列,像“@gmail”这样。结果是你找出了所有的gmail邮箱地址。在这个过程中,MySQL浏览所有的客户行和所有的customer_email区域字符在你得到结果前。这种特殊的情况没什么问题,但是当你搜索订单#: 10001时呢?

同样的事情,因为Magento针对特定的列时,经常在你的字符串前后添加"%"。所以如果你想要搜索#: 10001订单,Magento会转换成“%10001%”并在你的字符串前加Like语句。所以在最后Magento会发送这样的语句到MySQL“SELECT customer_email FROM…. WHERE customer_email LIKE ‘%10001%';这可能不是你所期待的,但它就是这么实现的。

如果我们想要改变这种行为并给MySQL(Magento)索引提速。我们需要在后台网格搜索时做些改变。最通用和用户友好的方式就是使用"*"字符替换MySQL的特殊字符"%"。

现在如果你想要使用“like”操作符,你将需要在字符串前、后或两侧添加。所以在我们改变后,你讲能找到所有的gmail通过在你的字符串前后添加"*"。所以,“@gmail”将变成“*@gmail*”。我希望你能看到这背后的思想。

让我们用下面的内容替换app/code/core/Mage/Adminhtml/Block/Widget/Grid.php中的私有方法_addColumnFilterToCollection($column)。我们只影响sales_order网格。

/**
 *
 */
protected function _addColumnFilterToCollection($column)
    {
       if ($this->getCollection()) {
           $field = ( $column->getFilterIndex() ) ? $column->getFilterIndex() : $column->getIndex();
           if ($column->getFilterConditionCallback()) {
               call_user_func($column->getFilterConditionCallback(), $this->getCollection(), $column);
           } else {
               $cond = $column->getFilter()->getCondition();
               /**  START WITH CODE FOR A NEW WAY OF SEARCHING
                * - if you look in app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Abstract.php
                * - you'll see that ->getCondition(); returns an array:
                * public function getCondition()
                * {
                *      return array('like'=>'%'.$this->_escapeValue($this->getValue()).'%');
                * }
                * - and _escapeValue returns:
                * protected function _escapeValue($value)
                * {
                *     return str_replace('_', '\_', $value);
                * }
                * - so we'll "unescape" it in case where we have [$cond['eq'] and unset($cond['like']);]
                */
               if ($field && isset($cond)) {
                   if($this->getAction() instanceof Mage_Adminhtml_Sales_OrderController) {
                       if (isset($cond['like'])) {
 
                           //cover case where like should go to equal; else means that we have at least one * so like should stay...
                           if (!(substr($cond['like'], -2) === '*%') && !(substr($cond['like'], 0,2) === '%*')) {
                               $cond['eq'] = str_replace('%', '', $cond['like']);
                               $cond['eq'] = str_replace('\_', '_', $cond['eq']); //This line was added with new revision
                               unset($cond['like']);
                           } else {
                               if (substr($cond['like'], 0,2) !== '%*') {
                                   $cond['like'] = substr($cond['like'],1);
                               } else {
                                   $cond['like'] = '%' . substr($cond['like'],2);
                               }
                               if (substr($cond['like'], -2) !== '*%') {
                                   $cond['like'] = substr($cond['like'], 0, -1);
                               } else {
                                   $cond['like'] = substr($cond['like'], 0, -2) . '%';
                               }
                           }
                       }
                   }
                   /*END WITH CODE FOR A NEW WAY OF SEARCHING*/
                   $this->getCollection()->addFieldToFilter($field , $cond);
               }
           }
       }
       return $this;
    }

在我们改变Magento核心文件后,再次尝试搜索订单#: 10。现在你能看到多少结果?花了多长时间呢?Magento现在使用order#索引。现在你所能搜索的数字10的类型是:“10”, “*10″, “*10*”和“10*”。注意,只有第一个是同等的,其它的使用了Like语句。

注意,你可以去掉“if($this->getAction() instanceof Mage_Adminhtml_Sales_OrderController) { … }”这个判断来将改变应用到整个后台。

你也可以选择重写Mage_Adminhtml_Block_Widget_Grid类而不是修改Magento核心文件。这个小技巧可以有效地提高我们客户的MySQL服务,

(责任编辑:好模板)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
热点内容