Строительный комплекс, где заявление в Laravel Eloquent с использованием - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть Eloquent\Builder $query, для которого я хочу использовать дополнительные вызовы where(), когда количество вызовов является неопределенным и берется из массива $filter, пример ниже:

$filter = [
    'or:email:=:ivantalanov@tfwno.gf',
    [
        'or:api_token:=:abcdefghijklmnopqrstuvwxyz',
        'and:login:!=:administrator',
    ],
];

Строки, когда анализируются, создают допустимые условия SQL, но проблема заключается в том, чтобы вставить их в замыкания, в которых присутствует группа (например, в строках 2 и 3 - массив является их «группой»).

Я знаю о функциональности Laravel, которая позволяет вставить функцию Closure в $query->where() для достижения того, что я хочу, но проблема, с которой я сталкиваюсь, заключается в создании этих сложных замыканий. Я должен перебрать каждую строку в группе и передать ее в сгенерированное замыкание следующим образом (где $item - результат анализа строки условия):

$closure = function ($query) use ($item)
{
    call_user_func_array(
        [$query, $item['function']], [$item['field'], $item['operator'], $item['values']]
    );
};

Теперь очевидная проблема с этим заключается в том, что, в то время как он легко делает простые замыкания, прохождение более одного условия совершенно невозможно. У меня вопрос: что я могу использовать для подготовки сложного оператора, который будет выполнен по запросу внутри замыкания?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Хорошо, думаю, я понял это.

Это метод, который будет возвращать конечный результат.

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

Используя это, вы можете изменить объект Eloquent\Builder так, как вам нравится, с глубоко вложенными фильтрами, которые объявляются динамически (например, получаются в запросе GET / POST).

0 голосов
/ 27 апреля 2018

Я думаю, это поможет вам:

В модели создайте область действия:

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

OR

Пример: публичная статическая функция getSearchedUserAuto ($ search_key, $ user_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;
    }

Посмотрите, работает ли это для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...