Buscar dentro de una Relacion de Eloquent (belongsTo)

En este pequeño articulo, vamos a revisar un concepto básico de como una búsqueda “anidada” utilizando las relaciones de Eloquent, el ORM que nos provee Laravel para interactuar con nuestra Base de Datos.

Caso de Uso

Digamos que tenemos un sistema de reserva de vuelos dentro de una aerolínea. En el cual vamos a tener dos modelos principales, el modelo User  y otro llamado Flight . Queremos ejecutar la búsqueda solo en los vuelos buscando por el nombre del usuario a quien esta asignado. Entonces, nos preguntamos, ¿cómo podemos devolver un conjunto de datos de vuelos buscando a través del modelo de usuarios? Vamos a ello.

Definiendo las Relaciones

Según el caso de uso anterior, sabemos que un vuelo (Flight) pertenece a un usuario (User), por lo cual declaramos la relación que vamos a utilizar dentro del modelo Flight


De esta manera, podremos realizar una consulta en el modelo de User a través del modelo de Flight. Si aun no has visto esto, te recomiendo que pases por la documentación para entender un poco como funcionan las relaciones de Eloquent.

Realizando la Consulta

Ahora vamos a nuestro controlador FlightController para este ejemplo, en el cual tendré un método index que recibe a través de una petición el username a ser buscado.


¿Que estamos haciendo? En el ejemplo anterior estamos buscando todos los vuelos donde el usuario sea similar al que recibo a través de la petición. Al método whereHas le pasamos la relación como el primer parámetro y luego pasamos la condición como la segunda usando una función anónima para ello. De esta manera, Eloquent nos provee una sintaxis bastante limpia para realizar este tipo de consultas.

También disponemos de los métodos orWhereHas, whereDoesntHave dentro de los modelos, los cuales se utilizan de manera similar.


Comparte este artículo

Entra en la discusión y deja tu comentario

  • Miguel Leon

    Hola Sergio Ojeda.

    Gracias por tu aporte.
    Sin embargo, me permito sugerirte, sin pretender menoscabar tus aportes.
    Por favor revisa tu script antes de lanzarlo, es más debería testearlo.
    1) return view(‘tickets.index’, compact(‘tickets));
    No está definido compact(‘tickets)); a mas que le falta cerrarlo con “‘”.
    Deberá ser acaso, compact(query ‘)); o compact(flight ‘)); ???

    2) El ejemplo debería, a mi gusto, ser un tanto mas extenso, hay que considerar que habemos mucha gente novata.
    Pregunta:
    Si el usuario tiene 2 columnas apellidos y nombres, como traería el vuelo con el nombre-full del usuario?

    Repito, gracias, por tu aporte Sergio.

    • IsraelOrtuno

      Se pueden añadir tantas cláusulas where como sean necesarias. El closure recibe una instancia del Query Builder por lo que se puede configurar la consulta a placer.

    • Sergio Ojeda

      @migueleonfer:disqus Muchisimas gracias, corregido! Me gustaría la verdad poder hacerlo mas extenso pero estamos limitados con el tiempo 🙁

  • Ramon Gajardo

    Hola cuando usamos la return $this->belongsTo(User::class); esto se refiere a una relación ya establecida en la base datos o en la migración ?. en caso que no utilizamos esto por ejemplo return $this->hasOne(‘AppSHIPINSTRUCT’, ‘INSTRUCTION_ID’,’INSTRUCTION_ID’); hay una diferencia de redimiento en esto cierto ? , porque uno se encuentra con base de datos ya establecidas que difícil pedir que creen indices y relaciones por parte quien administra la base de datos

    • Sergio Ojeda

      En ninguna de las dos. Cuando declaras una relacion de Eloquent, si no le indicas cuales son la foreing key y la local key por las convenciones, Laravel va asumir que la FK va ser el nombre de la relacion + _id (en el ejemplo user_id) y la local key seria id.

      Incluso no es necesario que dentro de la Base de Datos estén declaradas de manera estricta (es decir indicarle para que cree la FK), mas si lo haces rendirá mucho mejor.

  • Juan Manuel Anton

    Una consulta amigo podría usar tambien, la siguiente manera??? o sería incorrecto?? …
    $flight= Flight::with(‘user’)…. ?? Gracias amigo

    • Sergio Ojeda

      No seria incorrecto, mas no seria el caso de uso, cuando usas el ‘with’ le estas indicado a Eloquent que cargue la relacion dentro del modelo (es decir, traeme los Vuelos con sus usuarios usando eager-loading). Mientras que en este caso, estoy buscando los vuelos cuyo usuario sea el que esta en la consulta.

  • No seria mejor? User::where(‘username’, ‘like’, “%{$request->username}%”)->flights;
    Y definiendo en la clase User la relación

    public function flights()
    {
    return $this->hasMany(Flight::class);
    }

    • Sergio Ojeda

      Recordemos que esto son solo ejemplos para explicar un caso de uso de como buscar dentro de una relacion xD En tu caso podríamos hacer un caso de uso de buscar los vuelos de un Usuario que salgan a una hora en particular.

Veces