Laravel donde en el objeto de relación

4 minutos de lectura

avatar de usuario
licencia

Estoy desarrollando una API web con Laravel 5.0 pero no estoy seguro de una consulta específica que estoy tratando de construir.

Mis clases son las siguientes:

class Event extends Model {

    protected $table="events";
    public $timestamps = false;

    public function participants()
    {
        return $this->hasMany('App\Participant', 'IDEvent', 'ID');
    }

    public function owner()
    {
        return $this->hasOne('App\User', 'ID', 'IDOwner');
    }
}

y

class Participant extends Model {

    protected $table="participants";
    public $timestamps = false;

    public function user()
    {
        return $this->belongTo('App\User', 'IDUser', 'ID');
    }

    public function event()
    {
        return $this->belongTo('App\Event', 'IDEvent', 'ID');
    }
}

Ahora, quiero obtener todos los eventos con un participante específico. Probé con:

Event::with('participants')->where('IDUser', 1)->get();

pero el where se aplica la condición de Event y no en su Participants. Lo siguiente me da una excepción:

Participant::where('IDUser', 1)->event()->get();

Sé que puedo escribir esto:

$list = Participant::where('IDUser', 1)->get();
for($item in $list) {
   $event = $item->event;
   // ... other code ...
}

pero no parece muy eficiente enviar tantas consultas al servidor.

¿Cuál es la mejor manera de realizar un where a través de una relación modelo usando Laravel 5 y Eloquent?

  • ¿Cuál fue la excepción?

    – Danny Kopping

    1 mayo 2015 a las 15:39

avatar de usuario
Crembo

La sintaxis correcta para hacer esto en sus relaciones es:

Event::whereHas('participants', function ($query) {
    return $query->where('IDUser', '=', 1);
})->get();

Esto devolverá Eventos donde los Participantes tienen una ID de usuario de 1. Si el Participante no tiene una ID de usuario de 1, NO se devolverá el Evento.

Lee mas en https://laravel.com/docs/5.8/eloquent-relationships#eager-loading

  • Para ayudar a los lectores a comprender: Esto devolverá Eventos donde los Participantes tienen una ID de usuario de 1. Si el Participante no tiene una ID de usuario de 1, NO se devolverá el Evento.

    -Chuck Le Butt

    27 de septiembre de 2019 a las 13:26

  • Lo siento mucho. Me confundí y envié el comentario en el hilo equivocado.

    – Codificador de rayos

    15 de febrero de 2021 a las 1:23

  • @ChuckLeButt su comentario debe editarse en esta respuesta. Tu comentario tiene buen valor.

    – Derk Jan Speelman

    6 mayo 2021 a las 14:00

  • es su a o ¿Dónde tiene?

    – Jenuel Ganaw

    13 abr a las 8:44

avatar de usuario
Hamid Naghipour

La respuesta de @ Cermbo no está relacionada con esta pregunta. En esa respuesta, Laravel te daré todo Events si cada uno Event posee 'participants' con IdUser de 1.

Pero si quieres tener todo Events con toda 'participants' siempre que todos 'participants' tener un IdUser de 1, entonces deberías hacer algo como esto:

Event::with(["participants" => function($q){
    $q->where('participants.IdUser', '=', 1);
}])

NÓTESE BIEN:

En where use el nombre de su tabla, no el nombre del modelo.

  • Para ayudar a los lectores a comprender: a diferencia de la otra respuesta, esto devolverá TODOS los eventos, ya sea que el Participante tenga una identificación de usuario de 1 o no, pero solo incluirá el objeto Participante si la tiene.

    -Chuck Le Butt

    27 sep 2019 a las 13:27


para laravel 8.57+

Event::whereRelation('participants', 'IDUser', '=', 1)->get();

  • aquí está el original solicitud de extracciónsi alguien necesita entender cómo funciona.

    – William Turrell

    11 oct 2021 a las 0:23


  • Córneo. Súper cosa. También funciona así: php Event::whereRelation('participants', 'IDUser', 1)->get();

    – Norman Huth

    19 dic 2021 a las 20:35


avatar de usuario
Muhammad Shahzad

Con múltiples uniones, use algo como este código:

$userId = 44;
Event::with(["owner", "participants" => function($q) use($userId ){
    $q->where('participants.IdUser', '=', 1);
    //$q->where('some other field', $userId );
}])

avatar de usuario
brandon stewart

Usa este código:

return Deal::with(["redeem" => function($q){
    $q->where('user_id', '=', 1);
}])->get();

avatar de usuario
willianbabuu

para laravel 8 usa esto en su lugar

Event::whereHas('participants', function ($query) {
     $query->where('user_id', '=', 1);
})->get();

esto devolverá eventos que solo con participantes con ID de usuario 1 con esa relación de eventos,

avatar de usuario
Marek Gralikowski

Creé un ámbito de consulta personalizado en BaseModel (todos mis modelos amplían esta clase):

/**
 * Add a relationship exists condition (BelongsTo).
 *
 * @param  Builder        $query
 * @param  string|Model   $relation   Relation string name or you can try pass directly model and method will try guess relationship
 * @param  mixed          $modelOrKey
 * @return Builder|static
 */
public function scopeWhereHasRelated(Builder $query, $relation, $modelOrKey = null)
{
    if ($relation instanceof Model && $modelOrKey === null) {
        $modelOrKey = $relation;
        $relation   = Str::camel(class_basename($relation));
    }

    return $query->whereHas($relation, static function (Builder $query) use ($modelOrKey) {
        return $query->whereKey($modelOrKey instanceof Model ? $modelOrKey->getKey() : $modelOrKey);
    });
}

Puede usarlo en muchos contextos, por ejemplo:

Event::whereHasRelated('participants', 1)->isNotEmpty(); // where has participant with id = 1 

Además, puede intentar omitir el nombre de la relación y pasar solo el modelo:

$participant = Participant::find(1);
Event::whereHasRelated($participant)->first(); // guess relationship based on class name and get id from model instance

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad