¿Hay alguna forma de devolver un modelo padre con una relación pero solo devolver algunas de las filas de la relación utilizando un en donde?

Eso puede ser bastante confuso, déjame explicarte.

En este momento tengo 2 modelos, edificios y habitaciones, 1 edificio puede tener muchas habitaciones.

Quiero poder pasar una variedad de identificadores de sala y devolver los sitios y solo las salas que están en la matriz.

Heres lo que tengo en este momento

if($request->input('ids') && !is_null($request->input('ids'))){
    $ids = explode(',',$request->input('ids'));

    //Exploded ids looks like this    "2,4,11,55,56"

    $buildings = Buildings::join('rooms')->whereIn('rooms.id',$ids)->get();
} else {
    $buildings = Buildings::whereHas('rooms')->get();
}

Por el momento, esto devolverá todos los edificios que tienen una habitación cuya identificación está en la matriz ids y todas sus habitaciones, lo que termina devolviendo un edificio con más de 200 habitaciones. Lo necesito para devolver el edificio y SOLO las habitaciones que tienen una identificación en esa matriz.

¿Es posible?

Sé que puedo hacerlo de manera inversa y obtener todas las habitaciones como padre y luego obtener los edificios, pero necesito edificios para ser el padre ya que estoy ejecutando un foreach como este con los resultados

foreach($buildings as $key => $building){
    <h1>{{$building->name}}</h1>
    foreach($building->rooms as $k => $room){
      <p>{{$room->name}}</p>
    }
}

En caso de que siga siendo confuso, el escenario del mundo real es que estoy generando un PDF de habitaciones. Las habitaciones se pueden seleccionar marcando una casilla de verificación junto a la habitación en una lista de habitaciones. Entonces necesito poder pasar la matriz de identificadores de habitación y obtener todos los edificios que contienen una de las habitaciones. Luego obtenga todas las habitaciones para cada edificio donde la identificación de la habitación está en la matriz.

1
S_R 10 sep. 2018 a las 18:08

4 respuestas

La mejor respuesta

Primero debe saber, whereHas solo filtra el resultado principal pero no la relación de carga ansiosa. Por lo tanto, también debe aplicar ese filtro en la carga ansiosa. Me gusta esto

$ids = explode(',',$request->input('ids'));
$buildings = Buildings::with(['rooms' => function($q) use ($ids) {
    $q->whereIn('id', $ids);
}])->whereHas('rooms', function($q) use ($ids) {
    $q->whereIn('id', $ids);
})->get();

Aquí whereHas filtra edificios y usa with salas de filtros.

2
rkj 10 sep. 2018 a las 15:39

Puedes hacer esto con el siguiente código:

$ids = explode(',',$request->input('ids'));
$buildings = Buildings::whereHas('rooms', function($q) use ($ids) {
    $q->whereIn('id', $ids);
})->get();

Espero que esto ayude.

0
jogesh_pi 10 sep. 2018 a las 15:15
$ids = explode(',',$request->input('ids'));
$building_ids = Room::whereIn('id',$ids)->pluck('building_id');
$buildings_with_specific_rooms = Building::join('rooms', 'buildings.id', '=', 'rooms.building_id')->select('buildings.name', 'rooms.name')->whereIn('buildings.id', $building_ids)->whereIn('rooms.id', $ids)->get();

Espero que esto te ayude.

1
syam 10 sep. 2018 a las 15:28

Puede cargar ansiosamente la relación infantil y sacar los edificios de la colección de habitaciones:

$buildings = Room::with('building')
    ->with('building.room')
    ->whereIn('id', $ids)
    ->get()
    ->pluck('building');

Para que esto funcione, debe tener la relación declarada en los modelos Building y Room.

0
Thiago Barcala 10 sep. 2018 a las 15:35