2

Trying to get a hotel in detail for hotel management API, in which for some hotels, getting

$hotel->rooms

as object and for some as array. The eloquent query in Hotel model as below.

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

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

HotelRoom Model

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

Controller

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,
    ]);
}

response

{
    "id":"id",
    "name":"name",
    "rooms":{
        "1":{},
        "2":{}
    }       
}
{
    "id":"id",
    "name":"name",
    "rooms":[
        {},
        {},
    ]       
}
12
  • 1
    Which on you got? and which on you expect? Commented Mar 13, 2019 at 13:43
  • I got both in response. For example, for hotel-1 I got the first response, and for hotel-2 got the second one. I prefer the second response @hoseinz3 Commented Mar 13, 2019 at 13:44
  • 4
    Please share your rooms relation definition Commented Mar 13, 2019 at 13:46
  • 1
    Please can you add your controller method? Commented Mar 13, 2019 at 14:04
  • 1
    I think in the detail method you have tried some filtering, after use filter method you should add values method to re-index response Commented Mar 13, 2019 at 14:14

2 Answers 2

2

When you use unset on array, your array indexes remain for each item. Same as for collection->filter() or for array_filter() that is actually used in collection->filter(). That is why you need to rebuild the indexes:

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

to reindex the array.

Or use the foreach, but push values to new array:

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

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

    }

$data->rooms = $filteredRooms;

Or instead of foreach loop, use filter for collection in combination with values() :

$filteredRooms = $data->rooms->filter(function ($room, $key) {
    return (!$room->roomType)? false : true;
})->values();
Sign up to request clarification or add additional context in comments.

11 Comments

... "rooms": { "1": { "id": 2,...
@NoName, this replaces foreach. You can reassign value to $data->rooms = $filteredRooms after
$data->rooms = array_values($data->rooms->toArray()); tested this one @nikalz
this one works unset($data->rooms); $data->rooms = $fileteredRooms; after foreach. Where in foreach $filteredRooms[]=$room.
when you use unset, your array indexes remain for each item, same as for collection->filter() or for array_filter() that is actually used in collection->filter(). That is why you need to rebuild the indexes either way suggested in the answer above
|
1

After filtering array you have to re-index your array.

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

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

2 Comments

getting same response
but getting as array when the last line added inside foreach, is that correct format ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.