Добавить orWhere () к динамическому подзапросу c - PullRequest
4 голосов
/ 06 марта 2020

Пользователь может отправить форму поиска с вводом, таким как dog cat +bird. Ожидается, что он вернет все сообщения с заголовком, содержащим (dog ИЛИ cat) И bird.

Я считаю, что мне нужно добавить dog и cat в подзапрос, такой как:

protected function orLike(string $column, string $value): Builder
{
    return $this->builder
        ->where(function (Builder $subQuery) use ($column, $value) {
            $subQuery->orWhere($column, 'like', '%'.$value.'%'); // dog
            //$subQuery->orWhere($column, 'like', '%'.$value.'%'); // cat
            //$subQuery->orWhere($column, 'like', '%'.$value.'%'); etc...
        });
}

выше orLike - моя функция в al oop, которая выполняется для каждого проанализированный необязательный поисковый термин (dog, cat)

Как мне сделать так, чтобы каждый необязательный термин (dog или cat) ПРИЛОЖЕН к $subquery с orWhere() для каждый термин?

Прямо сейчас, очевидно, он запускает новый where() с одним подзапросом для каждого термина.

Не уверен, что я достаточно ясен. По сути, я пытаюсь создать довольно простой поисковый ввод, в котором пользователи могут ввести +bird -cat dog duck, что означает bird ДОЛЖНО быть в заголовке И cat НЕ ДОЛЖНО быть в заголовке И (содержит dog ИЛИ duck)

edit: дополнительная информация по запросу в комментариях

/*
usage: return $this->parseLike('title', '+dog cat -bird elephant duck');
*/

protected function parseLike(string $column, string $value)
{

    // [...] irrelevant code

    /*
    $terms is a collection of terms, such as:
    +dog
    cat
    -bird
    elephant
    duck
    */

    return $terms
        ->unique()
        ->map(function (string $term) {
            switch (\substr($term, 0, 1)) {
                case '+':
                    return ['like' => \substr($term, 1)]; // function "like()" is called for terms with operator "+" such as "+dog"
                case '-':
                    return ['notLike' => \substr($term, 1)]; // function "notLike()" is called for terms with operator "-" such as "-bird"
                default:
                    return ['orLike' => $term]; // function "orLike()" is called for terms with no operator, such as "elephant" or "duck" or "cat"
            }
        })
        ->each(function ($combination) use ($column) {
            collect($combination)
                ->reject(function ($term) {
                    return empty($term);
                })
                ->each(function (string $term, string $operator) use ($column) {
                    return $this->{$operator}($column, $term);
                });
        });
}

1 Ответ

1 голос
/ 07 марта 2020

Посмотрите на этот пример, я полагаю, что вы можете интегрировать его в свой код.

Все, что вам нужно, это создать массивы со значениями, которые вам 1. нужны, 2. не нужны, 3. могут быть

    $mustBe = ['dog', 'cat'];
    $mustNotBe = ['bird'];
    $mayBe = ['tiger', 'lion'];

    $model = SomeModel::query();

    foreach ($mustBe as $term){
        $model->where('title', 'like', '%'. $term . '%');
    }
    foreach ($mustNotBe as $term){
        $model->where('title', 'not like', '%'. $term . '%');
    }

    if($mayBe){
        $model->where(function ($query) use ($mayBe) {
            foreach ($mayBe as $term){
                $query->orWhere('title', 'like', '%'. $term . '%');
            }
        });
    }

    $result = $model->get();
    dd($result);

    // this builder will return something like this
    $result = SomeModel::where('title', 'like', '%dog%') // dog must be
        ->where('title', 'like', '%cat%') // cat must be
        ->where('title', 'not like', '%bird%') // bird must not be
        ->where(function ($query) {
            $query->orWhere('title', 'like', '%tiger%') // tiger may be
                  ->orWhere('title', 'like', '%lion%'); // lion may be
        })
    ->get(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...