Как создать несколько запросов к предложению Where с помощью Laravel Eloquent?

182

Я использую построитель запросов Laravel Eloquent, и у меня есть запрос, где я хочу предложение WHERE для нескольких вещей. Он работает, но он не изящный.

Пример:

$results = User::
      where('this', '=', 1)
    ->where('that', '=', 1)
    ->where('this_too', '=', 1)
    ->where('that_too', '=', 1)
    ->where('this_as_well', '=', 1)
    ->where('that_as_well', '=', 1)
    ->where('this_one_too', '=', 1)
    ->where('that_one_too', '=', 1)
    ->where('this_one_as_well', '=', 1)
    ->where('that_one_as_well', '=', 1)
    ->get();

Есть ли лучший способ сделать это, или я должен придерживаться этого метода?

  • 3
    Есть много возможностей с точки зрения того, как это можно упростить, но для этого потребуется более реалистичный код. Можете ли вы обновить код, чтобы он стал немного более реалистичным? Например, бывают случаи, когда несколько вызовов ->where(...) могут быть заменены ->whereIn(...) и так далее .
  • 0
    Решение @Jarek Tkaczyk должно быть ответом, я согласен. Но я бы предпочел, чтобы ваш код был похож на скрипт компоновщика для понимания и сопровождения.
Теги:
eloquent

13 ответов

278
Лучший ответ

В Laravel 5.3 вы можете использовать более гранулированные элементы, переданные как массив:

$query->where([
    ['column_1', '=', 'value_1'],
    ['column_2', '<>', 'value_2'],
    [COLUMN, OPERATOR, VALUE],
    ...
])

Лично я не нашел прецедента для этого только через несколько вызовов where, но факт, что вы можете его использовать.

С июня 2014 года вы можете передать массив в where

Если вы хотите, чтобы все wheres использовали оператор and, вы можете группировать их следующим образом:

$matchThese = ['field' => 'value', 'another_field' => 'another_value', ...];

// if you need another group of wheres as an alternative:
$orThose = ['yet_another_field' => 'yet_another_value', ...];

Тогда:

$results = User::where($matchThese)->get();

// with another group
$results = User::where($matchThese)
    ->orWhere($orThose)
    ->get();

Вышеприведенный результат приведет к такому запросу:

SELECT * FROM users
  WHERE (field = value AND another_field = another_value AND ...)
  OR (yet_another_field = yet_another_value AND ...)
  • 7
    Как вы указываете оператора?
  • 7
    @ Стифон Вы не делаете. В настоящее время это работает только с = .
Показать ещё 10 комментариев
55

Области запросов могут помочь сделать ваш код более читаемым.

http://laravel.com/docs/eloquent#query-scopes

Обновление этого ответа с помощью некоторого примера:

В вашей модели создайте методы областей, например:

public function scopeActive($query)
{
    return $query->where('active', '=', 1);
}

public function scopeThat($query)
{
    return $query->where('that', '=', 1);
}

Затем вы можете вызывать эти области при создании запроса:

$users = User::active()->that()->get();
37

Вы можете использовать подзапросы в анонимной функции, например:

 $results = User::where('this', '=', 1)
            ->where('that', '=', 1)
            ->where(function($query) {
                /** @var $query Illuminate\Database\Query\Builder  */
                return $query->where('this_too', 'LIKE', '%fake%')
                    ->orWhere('that_too', '=', 1);
            })
            ->get();
18

В этом случае вы можете использовать что-то вроде этого:

            User::where('this', '=', 1)
                ->whereNotNull('created_at')
                ->whereNotNull('updated_at')
                ->where(function($query){
                    return $query
                              ->whereNull('alias')
                              ->orWhere('alias', '=', 'admin');
                });

Он должен предоставить вам запрос типа:

select * from `user` 
where `user`.`this` = 1 
AND `user`.`created_at` is not null 
AND `user`.`updated_at` is not null 
AND (`alias` is null OR `alias` = 'admin')
4

Условия использования массива:

$users = User::where([
       'column1' => value1,
       'column2' => value2,
       'column3' => value3
])->get();

Будет генерировать запрос, например, ниже:

SELECT * FROM TABLE WHERE column1=value1 and column2=value2 and column3=value3

Условия, использующие функцию Antonymous:

$users = User::where('column1', '=', value1)
               ->where(function($query) use ($variable1,$variable2){
                    $query->where('column2','=',$variable1)
                   ->orWhere('column3','=',$variable2);
               })
              ->where(function($query2) use ($variable1,$variable2){
                    $query2->where('column4','=',$variable1)
                   ->where('column5','=',$variable2);
              })->get();

Будет генерировать запрос, например, ниже:

SELECT * FROM TABLE WHERE column1=value1 and (column2=value2 or column3=value3) and (column4=value4 and column5=value5)
4

Метод whereColumn может быть передан массив из нескольких условий. Эти условия будут объединены с помощью оператора and.

Пример:

$users = DB::table('users')
            ->whereColumn([
                ['first_name', '=', 'last_name'],
                ['updated_at', '>', 'created_at']
            ])->get();

$users = User::whereColumn([
                ['first_name', '=', 'last_name'],
                ['updated_at', '>', 'created_at']
            ])->get();

Для получения дополнительной информации проверьте этот раздел документации https://laravel.com/docs/5.4/queries#where-clauses

4

Несколько предложений where

    $query=DB::table('users')
        ->whereRaw("users.id BETWEEN 1003 AND 1004")
        ->whereNotIn('users.id', [1005,1006,1007])
        ->whereIn('users.id',  [1008,1009,1010]);
    $query->where(function($query2) use ($value)
    {
        $query2->where('user_type', 2)
            ->orWhere('value', $value);
    });

   if ($user == 'admin'){
        $query->where('users.user_name', $user);
    }

окончательно получить результат

    $result = $query->get();
2

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

Вам может быть полезно узнать о нормализации данных: http://en.wikipedia.org/wiki/Third_normal_form

1

Вы можете использовать красноречие в Laravel 5.3

Все результаты

UserModel::where('id_user', $id_user)
                ->where('estado', 1)
                ->get();

Частичные результаты

UserModel::where('id_user', $id_user)
                    ->where('estado', 1)
                    ->pluck('id_rol');
  • 2
    Чем это отличается от вопроса?
1

Обязательно применяйте любые другие фильтры к подзапросам, иначе они могут собрать все записи.

$query = Activity::whereNotNull('id');
$count = 0;
foreach ($this->Reporter()->get() as $service) {
        $condition = ($count == 0) ? "where" : "orWhere";
        $query->$condition(function ($query) use ($service) {
            $query->where('branch_id', '=', $service->branch_id)
                  ->where('activity_type_id', '=', $service->activity_type_id)
                  ->whereBetween('activity_date_time', [$this->start_date, $this->end_date]);
        });
    $count++;
}
return $query->get();
  • 0
    Спасибо за добавление 'use ($ service)'. Джулиан ответил почти на то, что мне было нужно. Ваш комментарий помог мне передать строку поиска в запрос.
-3
public function search()
{
    if (isset($_GET) && !empty($_GET))
    {
        $prepareQuery = '';
        foreach ($_GET as $key => $data)
        {
            if ($data)
            {
                $prepareQuery.=$key . ' = "' . $data . '" OR ';
            }
        }
        $query = substr($prepareQuery, 0, -3);
        if ($query)
            $model = Businesses::whereRaw($query)->get();
        else
            $model = Businesses::get();

        return view('pages.search', compact('model', 'model'));
    }
}
  • 0
    Это очень уязвимо для внедрения SQL.
-10

просто добавьте ИЛИ в 4-й параметр. например:

$results = User::where('this', '=', 1)
    ->where('that', '=', 1, 'OR')
    ->where('this_too', '=', 1, 'OR')
    ->where('that_too', '=', 1, 'OR')
    ->where('this_as_well', '=', 1, 'OR')
    ->where('that_as_well', '=', 1, 'OR')
    ->where('this_one_too', '=', 1, 'OR')
    ->where('that_one_too', '=', 1, 'OR')
    ->where('this_one_as_well', '=', 1, 'OR')
    ->where('that_one_as_well', '=', 1, 'OR')
    ->get();
-11
$variable = array('this' => 1,
                    'that' => 1
                    'that' => 1,
                    'this_too' => 1,
                    'that_too' => 1,
                    'this_as_well' => 1,
                    'that_as_well' => 1,
                    'this_one_too' => 1,
                    'that_one_too' => 1,
                    'this_one_as_well' => 1,
                    'that_one_as_well' => 1);

foreach ($variable as $key => $value) {
    User::where($key, '=', $value);
}
  • 0
    Это выполнит несколько запросов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню