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;
}