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 ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.