Jak utworzyć wielokrotne zapytanie klauzulowe przy użyciu Laravel Eloquent?


405

Używam konstruktora zapytań Laravel Eloquent i mam zapytanie, w którym chcę WHEREklauzulę dotyczącą wielu warunków. Działa, ale nie jest elegancki.

Przykład:

$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();

Czy jest na to lepszy sposób, czy powinienem trzymać się tej metody?


4
Istnieje wiele możliwości, w jaki sposób można to uprościć, ale wymagałoby to bardziej realistycznego kodu. Czy możesz zaktualizować kod, aby był trochę bardziej realistyczny? Na przykład zdarza się, że wiele ->where(...)połączeń można zastąpić ->whereIn(...)połączeniem itd .
jonathanmarvens,

1
Zgadzam się, że rozwiązanie @Jarek Tkaczyk powinno być odpowiedzią. Ale wolę twój kod jak skrypt konstruktora do zrozumienia i konserwacji.
Tiefan Ju

Odpowiedzi:


618

W Laravel 5.3 (i wciąż prawdziwy od wersji 7.x ) możesz użyć bardziej szczegółowego ciągu, który jest przekazywany jako tablica:

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

Osobiście nie znalazłem przypadku użycia tylko dla wielu wherepołączeń, ale faktem jest, że możesz go użyć.

Od czerwca 2014 r. Możesz przekazać tablicę do where

Tak długo, jak chcesz wszystkie operator wheresużycia and, możesz pogrupować je w ten sposób:

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

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

Następnie:

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

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

Powyższe spowoduje takie zapytanie:

SELECT * FROM users
  WHERE (field = value AND another_field = another_value AND ...)
  OR (yet_another_field = yet_another_value AND ...)

8
Jak określasz operatora?
Styphon

9
@Styphon Nie. Obecnie działa tylko z =.
Jarek Tkaczyk

5
@Styphon a co jeśli chcę zrobić: WHERE (a IS NOT NULL AND b=1) OR (a IS NULL AND b=2);?
alexglue

9
Możesz także przekazać tablicę takich warunków:$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get();
zera i

3
@jarek: Jak dołączyć whereNotInzgodnie z twoją odpowiedzią, mając inne wherecluazy?
Kalanka

93

Zakresy zapytań mogą pomóc w zwiększeniu czytelności kodu.

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

Aktualizacja tej odpowiedzi za pomocą jakiegoś przykładu:

W swoim modelu utwórz metody zakresów takie jak to:

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

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

Następnie możesz wywołać ten zakres podczas budowania zapytania:

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

jaka jest najlepsza praktyka w przypadku takiego stanu, zapytanie-> gdzie ('data_początkowa>> $ data_początkowa) nadal można używać zakresów?
Buwaneka Kalansuriya

72

Możesz użyć podkwerend w funkcji anonimowej, takiej jak ta:

 $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();

43

W takim przypadku możesz użyć czegoś takiego:

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

Powinien dostarczyć Ci zapytanie takie jak:

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')

36

Warunki korzystania z macierzy:

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

Wytworzy zapytanie jak poniżej:

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

Warunki korzystania z funkcji anonimowej:

$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();

Wytworzy zapytanie jak poniżej:

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

12

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

wreszcie uzyskam wynik

    $result = $query->get();

9

whereColumnSposób może być przekazywana szereg różnych warunkach. Warunki te zostaną połączone za pomocą andoperatora.

Przykład:

$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();

Aby uzyskać więcej informacji, sprawdź tę sekcję dokumentacji https://laravel.com/docs/5.4/queries#where-clauses


8
Model::where('column_1','=','value_1')->where('column_2 ','=','value_2')->get();

LUB

// If you are looking for equal value then no need to add =
Model::where('column_1','value_1')->where('column_2','value_2')->get();

LUB

Model::where(['column_1' => 'value_1','column_2' => 'value_2'])->get();

5

Pamiętaj, aby zastosować wszystkie inne filtry do zapytań podrzędnych, w przeciwnym razie lub może zgromadzić wszystkie rekordy.

$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();

Dziękujemy za dodanie „use ($ service)”. Odpowiedź Juljana była prawie tym, czego potrzebowałem. Twój komentarz pomógł mi przekazać szukany ciąg do zapytania.
Elliot Robert

5
$projects = DB::table('projects')->where([['title','like','%'.$input.'%'],
    ['status','<>','Pending'],
    ['status','<>','Not Available']])
->orwhere([['owner', 'like', '%'.$input.'%'],
    ['status','<>','Pending'],
    ['status','<>','Not Available']])->get();


3

Możesz używać elokwentnego w Laravel 5.3

Wszystkie wyniki

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

Częściowe wyniki

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

3
Czym różni się to od pytania?
veksen

2

użyj whereInwarunku i przekaż tablicę

$array = [1008,1009,1010];

User::whereIn('users.id', $array)->get();


1

Możesz użyć tablicy w klauzuli where, jak pokazano poniżej.

$result=DB::table('users')->where(array(
'column1' => value1,
'column2' => value2,
'column3' => value3))
->get();

1
DB::table('users')
            ->where('name', '=', 'John')
            ->orWhere(function ($query) {
                $query->where('votes', '>', 100)
                      ->where('title', '<>', 'Admin');
            })
            ->get();

1

Zgodnie z moją sugestią, jeśli wykonujesz filtr lub wyszukiwanie

powinieneś iść z:

        $results = User::query();
        $results->when($request->that, function ($q) use ($request) {
            $q->where('that', $request->that);
        });
        $results->when($request->this, function ($q) use ($request) {
            $q->where('this', $request->that);
        });
        $results->when($request->this_too, function ($q) use ($request) {
            $q->where('this_too', $request->that);
        });
        $results->get();

czy wyszukiwanie odbywa się po stronie phpside czy sql?
Mohamed

Strona Sql. Zapytanie SQL jest wykonywane jako parametr żądania. dawny. jeśli polecenie ma ten parametr. Następnie gdzie to = '' gdzie warunek dodany do zapytania.
Dhruv Raval


0

Używając czystego Elokwenta, zaimplementuj go w ten sposób. Ten kod zwraca wszystkich zalogowanych użytkowników, których konta są aktywne. $users = \App\User::where('status', 'active')->where('logged_in', true)->get();


0

Próbka kodu.

Po pierwsze :

$matchesLcl=[];

tablica jest wypełniana tutaj za pomocą żądanej liczby / pętli warunków, stopniowo:

if (trim($request->pos) != '') $matchesLcl['pos']= $request->pos;

i tu:

if (trim($operation) !== '')$matchesLcl['operation']= $operation;

i dalej z elokwentami, takimi jak:

if (!empty($matchesLcl))
    $setLcl= MyModel::select(['a', 'b', 'c', 'd'])
        ->where($matchesLcl)
        ->whereBetween('updated_at', array($newStartDate . ' 00:00:00', $newEndDate . ' 23:59:59'));
else 
    $setLcl= MyModel::select(['a', 'b', 'c', 'd'])
        ->whereBetween('updated_at', array($newStartDate . ' 00:00:00', $newEndDate . ' 23:59:59'));

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

Jest to bardzo podatne na wstrzyknięcie SQL.
rrrhys

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

Spowoduje to wykonanie wielu zapytań.
veksen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.