Laravel Где находится Где

Есть ли способ вернуть родительскую модель с отношением, но вернуть только некоторые строки отношений, используя where in?

Это может быть довольно запутанным, позвольте мне объяснить.

На данный момент у меня есть 2 модели, Здания и комнаты, 1 здание может иметь много комнат.

Я хочу иметь возможность передавать массив идентификаторов комнат и возвращать сайты и только те комнаты, которые находятся в массиве.

Вот что у меня есть на данный момент

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

На данный момент это вернет все здания, в которых есть комната, идентификатор которой находится в массиве ids, и все ее комнаты, что в конечном итоге вернет здание с более чем 200 комнатами. Мне нужно, чтобы он возвращал здание и ТОЛЬКО комнаты, у которых есть идентификатор в этом массиве.

Это возможно?

Я знаю, что могу сделать это обратным способом и получить все комнаты в качестве родителя, а затем получить здания, но мне нужно, чтобы здания были родителем, так как я запускаю такой foreach с результатами

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

Если это все еще сбивает с толку, в реальном мире я создаю PDF-файл комнат. Комнаты можно выбрать, установив флажок рядом с комнатой в списке комнат. Затем мне нужно передать массив идентификаторов комнат и получить все здания, в которых есть одна из комнат. Затем получите все комнаты для каждого здания, где идентификатор комнаты находится в массиве.


person S_R    schedule 10.09.2018    source источник


Ответы (4)


Во-первых, вам нужно знать, что whereHas фильтруется только ваш родительский результат, но не активное отношение загрузки. Таким образом, вам нужно применить этот фильтр и при нетерпеливой загрузке. Так

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

Здесь whereHas фильтровать здания и использовать with фильтровать комнаты.

person rkj    schedule 10.09.2018
comment
Блестяще, в этом есть смысл! Спасибо - person S_R; 10.09.2018

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

надеюсь, это поможет вам.

person syam    schedule 10.09.2018

вы можете сделать это с помощью следующего кода:

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

Надеюсь это поможет.

person jogesh_pi    schedule 10.09.2018
comment
Это не работает, это по-прежнему возвращает каждую комнату для сайта, если на сайте есть комната с идентификатором, который находится в массиве - person S_R; 10.09.2018

Вы можете загрузить дочернее отношение и получить здания из коллекции комнат:

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

Чтобы это работало, вам необходимо иметь отношение, объявленное как в моделях Building, так и в Room.

person Thiago Barcala    schedule 10.09.2018
comment
Потому что мне нужно запустить foreach для зданий, а затем foreach для каждой комнаты в зданиях. Здания должны быть родительским отношением - person S_R; 10.09.2018
comment
Один из других ответов решил мою проблему, спасибо за вашу помощь и предложение! - person S_R; 10.09.2018