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?


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

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

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

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

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)

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

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


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

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

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

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


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

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


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

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

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

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

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


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

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

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

Cela exécutera plusieurs requêtes.
veksen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.