¿Cómo crear múltiples consultas de cláusula Where usando Laravel Eloquent?

407

Estoy usando el generador de consultas Eloquent de Laravel y tengo una consulta donde quiero una WHEREcláusula sobre múltiples condiciones. Funciona, pero no es elegante.

Ejemplo:

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

¿Hay una mejor manera de hacer esto, o debería seguir con este método?

veksen
fuente
44
Hay muchas posibilidades en términos de cómo esto podría simplificarse, pero eso requeriría un código más realista. ¿Puedes actualizar el código para ser un poco más realista? Por ejemplo, hay veces en que múltiples ->where(...)llamadas pueden ser reemplazados por una ->whereIn(...)llamada, etcétera .
jonathanmarvens
2
La solución de @Jarek Tkaczyk debería ser la respuesta, estoy de acuerdo. Pero preferiría su código como script de generador para la comprensión y el mantenimiento.
Tiefan Ju

Respuestas:

621

En Laravel 5.3 (y sigue siendo cierto a partir de 7.x ) puede usar más wheres granulares pasados ​​como una matriz:

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

Personalmente, no he encontrado un caso de uso para esto solo con varias wherellamadas, pero el hecho es que puede usarlo.

Desde junio de 2014 puede pasar una matriz a where

Mientras desee todos los operadores de wheresuso and, puede agruparlos de esta manera:

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

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

Entonces:

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

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

Lo anterior dará como resultado dicha consulta:

SELECT * FROM users
  WHERE (field = value AND another_field = another_value AND ...)
  OR (yet_another_field = yet_another_value AND ...)
Jarek Tkaczyk
fuente
8
¿Cómo se especifica el operador?
Styphon
99
@Styphon No lo haces. Actualmente solo funciona con =.
Jarek Tkaczyk
55
@Styphon y ¿qué pasa si quiero hacer WHERE (a IS NOT NULL AND b=1) OR (a IS NULL AND b=2);:?
alexglue
99
También puede pasar una serie de condiciones como esta:$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'], ])->get();
ceros y unos
3
@jarek: ¿Cómo incluyo el de whereNotInacuerdo con su respuesta al tener otros wherecluases?
Kalanka
93

Los ámbitos de consulta pueden ayudarlo a permitir que su código sea más legible.

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

Actualizando esta respuesta con algún ejemplo:

En su modelo, cree métodos de ámbitos como este:

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

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

Luego, puede llamar a estos ámbitos mientras crea su consulta:

$users = User::active()->that()->get();
Luis Dalmolin
fuente
¿Cuál es la mejor práctica para una condición como esta, query-> where ('start_date'> $ startDate) todavía está bien usar Scopes?
Buwaneka Kalansuriya
72

Puede usar subconsultas en funciones anónimas como esta:

 $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
fuente
43

En este caso, podría usar algo como esto:

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

Debería proporcionarle una consulta como:

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
fuente
36

Condiciones usando Array:

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

Producirá la consulta como abajo:

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

Condiciones que utilizan la función antónimo:

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

Producirá la consulta como abajo:

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

Múltiples cláusulas 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);
    }

finalmente obteniendo el resultado

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

El whereColumnmétodo se puede pasar una serie de condiciones múltiples. Estas condiciones se unirán utilizando el andoperador.

Ejemplo:

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

Para obtener más información, consulte esta sección de la documentación https://laravel.com/docs/5.4/queries#where-clauses

Alex Quintero
fuente
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();
DsRaj
fuente
5

Asegúrese de aplicar cualquier otro filtro a las subconsultas, de lo contrario, podría recopilar todos los registros.

$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
fuente
Gracias por agregar el 'uso ($ servicio)'. La respuesta de Juljan fue casi lo que necesitaba. Su comentario me ayudó a pasar mi cadena de búsqueda a la consulta.
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
fuente
3

Sin un ejemplo real, es difícil hacer una recomendación. Sin embargo, nunca he necesitado usar tantas cláusulas WHERE en una consulta y puede indicar un problema con la estructura de sus datos.

Puede ser útil para usted aprender sobre la normalización de datos: http://en.wikipedia.org/wiki/Third_normal_form

Aaron Cicali
fuente
3

Puedes usar elocuente en Laravel 5.3

Todos los resultados

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

Resultados parciales

UserModel::where('id_user', $id_user)
                    ->where('estado', 1)
                    ->pluck('id_rol');
Cristhian Carreño
fuente
3
¿Cómo es esto diferente de la pregunta?
veksen
2

usar whereIncondición y pasar la matriz

$array = [1008,1009,1010];

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

Rahul Tathod
fuente
1

Puede usar la matriz en la cláusula where como se muestra a continuación.

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

Según mi sugerencia si estás haciendo un filtro o buscando

entonces deberías ir 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();
Dhruv Raval
fuente
¿La búsqueda ocurre en el lado phpside o sql?
Sr. Mohamed
Sql lado. La consulta SQL se ejecuta como parámetro de solicitud. ex. si requrst tiene este parámetro. Entonces, donde esto = '' donde se agregó la condición a la consulta.
Dhruv Raval
1

Utilizar este

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

Usando Eloquent puro, impleméntelo así. Este código devuelve todos los usuarios registrados cuyas cuentas están activas. $users = \App\User::where('status', 'active')->where('logged_in', true)->get();

Craig GeRa
fuente
0

Una muestra de código.

Primeramente :

$matchesLcl=[];

la matriz se llena aquí usando el conteo / ciclo de condiciones deseado , de forma incremental:

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

y aquí:

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

y más con elocuentes como:

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
fuente
-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
fuente
Esto es muy vulnerable a la inyección 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
fuente
Esto ejecutará múltiples consultas.
veksen