Php 使用Laravel中的语句雄辩地构建复合物
我有一个Php 使用Laravel中的语句雄辩地构建复合物,php,laravel,Php,Laravel,我有一个elount\Builder$query,我想使用额外的where()调用,其中调用量是不确定的,并且是从数组$filter中获取的,示例如下: $filter = [ 'or:email:=:ivantalanov@tfwno.gf', [ 'or:api_token:=:abcdefghijklmnopqrstuvwxyz', 'and:login:!=:administrator', ], ]; 解析字符串时,会生成有效的S
elount\Builder$query
,我想使用额外的where()
调用,其中调用量是不确定的,并且是从数组$filter
中获取的,示例如下:
$filter = [
'or:email:=:ivantalanov@tfwno.gf',
[
'or:api_token:=:abcdefghijklmnopqrstuvwxyz',
'and:login:!=:administrator',
],
];
解析字符串时,会生成有效的SQL条件,但问题在于将它们粘贴到存在组的闭包中(如示例中的字符串2和3-数组是它们的“组”)
我知道Laravel的功能允许将闭包
函数粘贴到$query->where()
中以实现我想要的,但我面临的问题实际上是构建那些复杂的闭包。我必须遍历组中的每个字符串,并将其传递到这样生成的闭包中(其中,$item
是解析条件字符串的结果):
现在明显的问题是,虽然它很容易实现简单的闭包,但传递多个条件显然是不可能的。
我的问题是,我可以用什么来准备一个复杂的语句,以便在闭包中的查询上执行?我想这会对您有所帮助: 在模型中创建范围:
public static function scopeGetResultList($query) {
return $query->where(function ($query) use ($item) {
$query->where('group_user_holder_type', '=', 1)
->orWhere('group_user_holder_type', '=', 0);
});
}
或
例如:
公共静态函数getSearchedUserAuto($search\u key,$user\u id)
{
$users = DB::table((new User)->getTable().' as U')
->select('U.*', 'CT.city_name', 'C.nicename')
->leftJoin((new Country)->getTable().' as C', 'C.country_id', '=', 'U.user_country')
->leftJoin((new City)->getTable().' as CT', 'CT.city_id', '=', 'U.user_city')
->where(function($query) use ($search_key){
$query->where('U.user_full_name', 'like', '%'.$search_key.'%')
->orWhere('U.user_email', 'like', '%'.$search_key.'%');
})
->where(function($query) use ($search_key){
$query->where('U.user_full_name', 'like', '%'.$search_key.'%')
->orWhere('U.user_email', 'like', '%'.$search_key.'%');
})
->where('U.status', '=', 1)
->where('U.user_id', '!=', $user_id)
->get();
return $users;
}
看看它是否对你有用。好的,我想我知道了 这是将返回最终结果的方法
public function parse_filter(Builder &$query, array $filter)
{
$groups = $this->_prepare_groups($filter);
return $this->_parse_groups($query, $groups);
}
这些方法将把初始数组解析成更有用的东西
private function _prepare_groups(array $filter)
{
foreach ($filter as $key => $item) {
if (is_array($item)) {
$groups[] = $this->_prepare_groups($item);
}
if (is_string($item)) {
$simple_filter = $this->_parse_simple_filter($item);
$groups[] = $simple_filter;
$simple_filter = null;
}
}
return $groups;
}
private function _parse_simple_filter(string $filter)
{
$filter_data = explode(':', $filter);
$simple_filter['function'] = $filter_data[0] === 'and' ? 'where' : 'orWhere';
$simple_filter['field'] = $filter_data[1];
$simple_filter['operator'] = $filter_data[2];
$simple_filter['values'] = $filter_data[3];
return $simple_filter;
}
这里是最神奇的地方。正如您所看到的,闭包是对这个方法的递归调用
private function _parse_groups(Builder &$query, array $groups)
{
foreach ($groups as $operator => $group) {
if (!array_key_exists('function', $group)) {
$closure = function ($query) use ($group)
{
$this->_parse_groups($query, $group);
};
$query->where($closure);
} else {
$query->{$group['function']}($group['field'], $group['operator'], $group['values']);
}
}
return $query;
}
使用此选项,您可以通过动态声明的深度嵌套过滤器(例如,在GET/POST请求中接收)修改
Eloquent\Builder
对象。是否需要where子句中的类似内容:where(a=1和b=2)或(c=2和f=5)?是的,这就是它的要点。我已经回答了。请检查并让我知道它是否对您有效。我会帮助您。这不是很好,抱歉。我能够手工编写所需的where链接,我要寻找的是一些技巧,关于如何制作一个方法,该方法将接受初始查询和一组筛选参数,并对其进行处理,从而生成一个new Eloquent\Builder对象,该对象具有应用于它的所有位置。
private function _parse_groups(Builder &$query, array $groups)
{
foreach ($groups as $operator => $group) {
if (!array_key_exists('function', $group)) {
$closure = function ($query) use ($group)
{
$this->_parse_groups($query, $group);
};
$query->where($closure);
} else {
$query->{$group['function']}($group['field'], $group['operator'], $group['values']);
}
}
return $query;
}