Laravel красноречивый: получение объекта вместо массива

#laravel #laravel-5 #eloquent

#laravel #laravel-5 #красноречивый

Вопрос:

Попытка получить отель в деталях для API управления отелем, в котором для некоторых отелей получение

$отель-> номера

как объекта, а для некоторых как массива. Запрос eloquent в модели отеля, как показано ниже.

 public function detail($hotelid) { 
    return $this->with(['rooms','roomType'])->find($hotelid);
}

public function rooms() {
    return $this->hasMany(HotelRooms::class, 'hotels_id')->where('status','active');
}

  

Модель гостиничного номера

 public function roomType(){
   return $this->hasOne(RoomType::class,'id','room_type_id')->where('status','active');
}
  

Контроллер

 public function __construct(){
    $this->model = new Hotel();
}

public function hotelDetail(Request $request){

    $data = $this->model->detail($request->input('hotel_id'));

    foreach($data->rooms as $key=>$room){

        if(!$room->roomType){
            unset($data->rooms[$key]);
            continue;
        }

    }

    return response()->json([
         'status' => true,
         'status_message' => 'successful',
         'data' => $data,
    ]);
}

  

ответ

 {
    "id":"id",
    "name":"name",
    "rooms":{
        "1":{},
        "2":{}
    }       
}
  
 {
    "id":"id",
    "name":"name",
    "rooms":[
        {},
        {},
    ]       
}
  

Комментарии:

1. Что у вас получилось? и чего же вы ожидаете?

2. В ответ я получил и то, и другое. Например, для hotel-1 я получил первый ответ, а для hotel-2 — второй. Я предпочитаю второй ответ @hoseinz3

3. Пожалуйста, поделитесь своим определением отношения комнат

4. Пожалуйста, не могли бы вы добавить свой метод контроллера?

5. Я думаю, что в методе detail вы попробовали некоторую фильтрацию, после использования filter метода вам следует добавить values метод для переиндексации ответа

Ответ №1:

Когда вы используете unset on array, индексы вашего массива сохраняются для каждого элемента. То же, что для collection->filter() или для array_filter() того, что фактически используется в collection->filter() . Вот почему вам нужно перестроить индексы:

 $data->rooms = array_values($data->rooms->toArray());
  

для переиндексации массива.

Или используйте foreach , но помещайте значения в новый массив:

 $filteredRooms = [];
   foreach($data->rooms as $key=>$room){

        if(!$room->roomType){
           continue;
        }
        $filteredRooms[] = $room;

    }

$data->rooms = $filteredRooms;
  

Или вместо foreach цикла используйте filter для сбора в сочетании с values() :

 $filteredRooms = $data->rooms->filter(function ($room, $key) {
    return (!$room->roomType)? false : true;
})->values();
  

Комментарии:

1. ... "rooms": { "1": { "id": 2,...

2. @NoName, это заменяет foreach . Вы можете переназначить значение на $data->rooms = $filteredRooms после

3. $data->rooms = array_values($data->rooms->toArray()); протестировал это @nikalz

4. это работает unset($data->rooms); $data->rooms = $fileteredRooms; после foreach. Где в foreach $filteredRooms[]=$room .

5. когда вы используете unset , индексы вашего массива сохраняются для каждого элемента, такие же, как для collection-> filter() или для array_filter(), который фактически используется в collection-> filter(). Вот почему вам нужно перестроить индексы любым способом, предложенным в ответе выше

Ответ №2:

После фильтрации массива вам необходимо повторно проиндексировать свой массив.

 foreach($data->rooms as $key=>$room){

    if(!$room->roomType){
        unset($data->rooms[$key]);
        continue;
    }
}
$data->rooms = $data->rooms->values();
  

Комментарии:

1. получение того же ответа

2. но получение в виде массива при добавлении последней строки внутри foreach, это правильный формат?