Comment créer plusieurs requêtes de clause Where à l'aide de Laravel Eloquent?

407

J'utilise le générateur de requêtes Laravel Eloquent et j'ai une requête où je veux une WHEREclause sur plusieurs conditions. Cela fonctionne, mais ce n'est pas élégant.

Exemple:

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

Existe-t-il une meilleure façon de procéder ou dois-je m'en tenir à cette méthode?

veksen
la source
4
Il existe de nombreuses possibilités en termes de simplification, mais cela nécessiterait un code plus réaliste. Pouvez-vous mettre à jour le code pour être un peu plus réaliste? Par exemple, il y a des moments où plusieurs ->where(...)appels peuvent être remplacés par un ->whereIn(...)appel, et cetera .
jonathanmarvens
2
La solution de @Jarek Tkaczyk devrait être la réponse, je suis d'accord. Mais je préfère votre code comme un script de générateur pour la compréhension et la maintenance.
Tiefan Ju

Réponses:

621

Dans Laravel 5.3 (et toujours vrai à partir de 7.x ), vous pouvez utiliser des emplacements plus granulaires passés sous forme de tableau:

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

Personnellement, je n'ai pas trouvé de cas d'utilisation pour cela sur plusieurs whereappels, mais le fait est que vous pouvez l'utiliser.

Depuis juin 2014, vous pouvez transmettre un tableau à where

Tant que vous voulez tous les opérateurs d' wheresutilisation and, vous pouvez les regrouper de cette façon:

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

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

Alors:

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

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

Ce qui précède entraînera une telle requête:

SELECT * FROM users
  WHERE (field = value AND another_field = another_value AND ...)
  OR (yet_another_field = yet_another_value AND ...)
Jarek Tkaczyk
la source
8
Comment spécifiez-vous l'opérateur?
Styphon
9
@Styphon Non. Actuellement, cela ne fonctionne qu'avec =.
Jarek Tkaczyk
5
@Styphon et si je veux faire: WHERE (a IS NOT NULL AND b=1) OR (a IS NULL AND b=2);?
alexglue
9
Vous pouvez également passer un tableau de conditions comme ceci:$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get();
zéros et uns
3
@jarek: Comment puis-je inclure le whereNotInselon votre réponse avec d'autres wherecluases?
Kalanka
93

Les étendues de requête peuvent vous aider à rendre votre code plus lisible.

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

Mise à jour de cette réponse avec un exemple:

Dans votre modèle, créez des méthodes d'étendues comme celle-ci:

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

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

Ensuite, vous pouvez appeler ces étendues lors de la création de votre requête:

$users = User::active()->that()->get();
Luis Dalmolin
la source
quelle est la meilleure pratique pour une condition comme celle-ci, query-> where ('start_date'> $ startDate) est-il toujours acceptable d'utiliser des étendues?
Buwaneka Kalansuriya
72

Vous pouvez utiliser des sous-requêtes dans une fonction anonyme comme ceci:

 $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();
Juljan
la source
43

Dans ce cas, vous pouvez utiliser quelque chose comme ceci:

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

Il devrait vous fournir une requête comme:

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')
alexglue
la source
36

Conditions utilisant Array:

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

Produira une requête comme ci-dessous:

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

Conditions utilisant la fonction Antonyme:

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

Produira une requête comme ci-dessous:

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

Clauses WHERE multiples

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

enfin obtenir le résultat

    $result = $query->get();
Majbah Habib
la source
9

La whereColumnméthode peut recevoir un tableau de plusieurs conditions. Ces conditions seront jointes à l'aide duand opérateur.

Exemple:

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

Pour plus d'informations, consultez cette section de la documentation https://laravel.com/docs/5.4/queries#where-clauses

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

OU

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

OU

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

Assurez-vous d'appliquer tout autre filtre aux sous-requêtes, sinon le ou pourrait rassembler tous les enregistrements.

$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();
adamk
la source
Merci d'avoir ajouté 'use ($ service)'. La réponse de Juljan était presque ce dont j'avais besoin. Votre commentaire m'a aidé à passer ma chaîne de recherche à la requête.
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();
Lim Kean Phang
la source
3

Sans véritable exemple, il est difficile de faire une recommandation. Cependant, je n'ai jamais eu besoin d'utiliser autant de clauses WHERE dans une requête et cela peut indiquer un problème avec la structure de vos données.

Il peut vous être utile de vous renseigner sur la normalisation des données: http://en.wikipedia.org/wiki/Third_normal_form

Aaron Cicali
la source
3

Vous pouvez utiliser éloquent dans Laravel 5.3

Tous les résultats

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

Résultats partiels

UserModel::where('id_user', $id_user)
                    ->where('estado', 1)
                    ->pluck('id_rol');
Cristhian Carreño
la source
3
En quoi est-ce différent de la question?
veksen
2

utiliser la whereIncondition et passer le tableau

$array = [1008,1009,1010];

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

Rahul Tathod
la source
1

Vous pouvez utiliser la clause array in where comme indiqué ci-dessous.

$result=DB::table('users')->where(array(
'column1' => value1,
'column2' => value2,
'column3' => value3))
->get();
Abhijeet Navgire
la source
1
DB::table('users')
            ->where('name', '=', 'John')
            ->orWhere(function ($query) {
                $query->where('votes', '>', 100)
                      ->where('title', '<>', 'Admin');
            })
            ->get();
pardeep
la source
1

Selon ma suggestion si vous effectuez un filtrage ou une recherche

alors vous devriez aller avec:

        $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();
Dhruv Raval
la source
la recherche se fait-elle du côté phpside ou sql?
M. Mohamed
Côté sql. La requête SQL s'exécute comme paramètre de requête. ex. si requrst a ce paramètre. Puis où this = '' où la condition a été ajoutée à la requête.
Dhruv Raval
1

Utilisez ceci

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

En utilisant Eloquent pur, implémentez-le ainsi. Ce code renvoie tous les utilisateurs connectés dont les comptes sont actifs. $users = \App\User::where('status', 'active')->where('logged_in', true)->get();

Craig GeRa
la source
0

Un exemple de code.

D'abord :

$matchesLcl=[];

le tableau est rempli ici en utilisant le nombre / boucle de conditions souhaité , de manière incrémentielle:

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

et ici:

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

et plus loin avec des éloquents comme:

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'));
CodeToLife
la source
-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'));
    }
}
Muhammad Arslan
la source
Ceci est très vulnérable à l'injection 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);
}
Yuri Lazo
la source
Cela exécutera plusieurs requêtes.
veksen