¿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?


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

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

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

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

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)

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

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


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

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

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

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


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

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


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

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

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

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

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


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

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

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

Esto ejecutará múltiples consultas.
veksen
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.