Come creare una query a più clausole Where utilizzando Laravel Eloquent?


407

Sto usando il generatore di query Laravel Eloquent e ho una query in cui voglio un WHERE clausola a più condizioni. Funziona, ma non è elegante.

Esempio:

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

C'è un modo migliore per farlo o devo attenermi a questo metodo?


4
Ci sono molte possibilità in termini di come questo potrebbe essere semplificato, ma ciò richiederebbe un codice più realistico. Puoi aggiornare il codice per renderlo un po 'più realistico? Ad esempio, ci sono momenti in cui più ->where(...)chiamate possono essere sostituite da una ->whereIn(...)chiamata, eccetera .
jonathanmarvens,

2
La soluzione di @Jarek Tkaczyk dovrebbe essere la risposta, sono d'accordo. Ma preferirei il tuo codice come lo script del builder per comprensione e manutenzione.
Tiefan Ju,

Risposte:


621

In Laravel 5.3 (e ancora vero a partire da 7.x ) è possibile utilizzare posizioni più granulari passate come un array:

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

Personalmente non ho trovato il caso d'uso per questo solo su più wherechiamate, ma in realtà è possibile utilizzarlo.

Da giugno 2014 è possibile passare un array a where

Finché vuoi tutto l' operatore wheresuse and, puoi raggrupparli in questo modo:

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

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

Poi:

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

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

Quanto sopra comporterà tale query:

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

8
Come si specifica l'operatore?
Styphon,

9
@Styphon No. Attualmente funziona solo con =.
Jarek Tkaczyk,

5
@Styphon E se io voglio fare: WHERE (a IS NOT NULL AND b=1) OR (a IS NULL AND b=2);?
alexglue,

9
Puoi anche passare una serie di condizioni come questa:$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get();
zeri-e-uno

3
@jarek: come posso includere il whereNotInsecondo in base alla tua risposta con altre whereinformazioni?
Kalanka,

93

Gli ambiti di query possono aiutarti a rendere il tuo codice più leggibile.

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

Aggiornamento di questa risposta con alcuni esempi:

Nel tuo modello, crea metodi di scope come questo:

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

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

Quindi, è possibile chiamare questi ambiti durante la creazione della query:

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

qual è la migliore pratica per una condizione come questa, query-> dove ('start_date'> $ startDate) è ancora accettabile usare Scopes?
Buwaneka Kalansuriya,

72

È possibile utilizzare le query secondarie in funzione anonima in questo modo:

 $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

In questo caso potresti usare qualcosa del genere:

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

Dovrebbe fornirti una domanda come:

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

Condizioni che utilizzano l'array:

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

Produrrà query come qui sotto:

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

Condizioni che utilizzano la funzione 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();

Produrrà query come qui sotto:

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

12

Clausole multiple multiple

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

finalmente ottenere il risultato

    $result = $query->get();

9

Il whereColumnmetodo può essere passato a una matrice di più condizioni. Queste condizioni verranno unite utilizzando l' andoperatore.

Esempio:

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

Per ulteriori informazioni, consultare questa sezione della documentazione https://laravel.com/docs/5.4/queries#where-clauses


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

O

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

O

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

5

Assicurati di applicare qualsiasi altro filtro alle query secondarie, altrimenti il ​​o potrebbe raccogliere tutti i record.

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

Grazie per aver aggiunto "use ($ service)". La risposta di Juljan era quasi ciò di cui avevo bisogno. Il tuo commento mi ha aiutato a passare la mia stringa di ricerca alla query.
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

Senza un vero esempio, è difficile formulare una raccomandazione. Tuttavia, non ho mai avuto bisogno di usare così tante clausole WHERE in una query e ciò potrebbe indicare un problema con la struttura dei dati.

Potrebbe esserti utile conoscere la normalizzazione dei dati: http://en.wikipedia.org/wiki/Third_normal_form


3

Puoi usare eloquent in Laravel 5.3

Tutti i risultati

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

Risultati parziali

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

3
In che cosa differisce dalla domanda?
Veksen,

2

usa whereIncondizione e passa l'array

$array = [1008,1009,1010];

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


1

È possibile utilizzare l'array nella clausola where come mostrato di seguito.

$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

Secondo il mio suggerimento, se stai facendo il filtro o la ricerca

allora dovresti andare con:

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

la ricerca avviene nel lato phpside o sql?
Mohamed,

Lato mq. La query SQL viene eseguita come parametro di richiesta. ex. se requrst ha questo parametro. Quindi dove this = '' dove condizione aggiunta alla query.
Dhruv Raval,

1

Usa questo

$users = DB::table('users')
                    ->where('votes', '>', 100)
                    ->orWhere('name', 'John')
                    ->get();

0

Usando Eloquent puro, implementalo in questo modo. Questo codice restituisce tutti gli utenti che hanno effettuato l'accesso i cui account sono attivi. $users = \App\User::where('status', 'active')->where('logged_in', true)->get();


0

Un esempio di codice.

Innanzitutto:

$matchesLcl=[];

l'array viene riempito qui usando il conteggio / loop di condizioni desiderato , in modo incrementale:

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

e qui:

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

e ulteriormente con eloquenti come:

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

Questo è molto vulnerabile all'iniezione 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);
}

Ciò eseguirà più query.
Veksen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.