数据库查询中对 like 的值进行转义
在laravel中,如果要进行数据库的like模糊查询,可以这么做:
$query->where('title','like' , "%".$keyword."%");
不过这种做法却有几个问题:
- 重复书写like
$keyword
可能包含%
和_
,这两个特殊字符将能够把数据库中所有的记录都能查找出来。
Laravel China社区的做法是直接把%
和_
去掉了。
为了避免这种情况,我们可以自定义一个函数将我们的字符进行转义。
function escape_like_str($str)
{
$like_escape_char = '!';
return str_replace([$like_escape_char, '%', '_'], [
$like_escape_char.$like_escape_char,
$like_escape_char.'%',
$like_escape_char.'_',
], $str);
}
使用时像这样
$query->where('title','like' , "%".escape_like_str($keyword)."%");
或者参考这个trait
<?php
namespace App\Models\Traits;
trait LikeScope
{
/**
* @param \Illuminate\Database\Eloquent\Builder $query
* @param $column
* @param $value
* @param $side
* @param $isNotLike
* @param $isAnd
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeLike($query, $column, $value, $side = 'both', $isNotLike = false, $isAnd = true)
{
$operator = $isNotLike ? 'not like' : 'like';
$escape_like_str = function ($str) {
$like_escape_char = '!';
return str_replace([$like_escape_char, '%', '_'], [
$like_escape_char.$like_escape_char,
$like_escape_char.'%',
$like_escape_char.'_',
], $str);
};
switch ($side) {
case 'none':
$value = $escape_like_str($value);
break;
case 'before':
case 'left':
$value = "%{$escape_like_str($value)}";
break;
case 'after':
case 'right':
$value = "{$escape_like_str($value)}%";
break;
case 'both':
case 'all':
default:
$value = "%{$escape_like_str($value)}%";
break;
}
return $isAnd ? $query->where($column, $operator, $value) : $query->orWhere($column, $operator, $value);
}
public function scopeOrLike($query, $column, $value, $side = 'both', $isNotLike = false)
{
return $query->like($column, $value, $side, $isNotLike, false);
}
public function scopeNotLike($query, $column, $value, $side = 'both', $isAnd = true)
{
return $query->like($column, $value, $side, true, $isAnd);
}
public function scopeOrNotLike($query, $column, $value, $side = 'both')
{
return $query->like($column, $value, $side, true, false);
}
}
使用方法
<?php
use App\Models\Traits\LikeScope;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
use LikeScope;
public function scopeSearch($query, $keyword)
{
return $query->like('title', $keyword);
}
}
我的代码参考了codeigniter的代码实现,欢迎各位批评或提出建议。如果有更好的方法也请多多指教
本帖已被设为精华帖!
本帖由系统于 4年前 自动加精
感谢
function escape_like_str($str){
$like_escape_char = “//“;
return str_replace([$like_escape_char, ‘%’, ‘‘], [
$like_escape_char.$like_escape_char,
$like_escape_char.’%’,
$like_escape_char.’‘,
], $str);
}
$like_escape_char 应该为 ‘//‘;否则关键字包含 % _ 就搜不到