toneymutinda's avatar

Querying Relationships

Hey guys, I am developing a hotel reservation system. My models include user, hotel, room and reservation. A room belongs to a hotel, whereas a reservation belongs to a room. My room schema includes a reserved column that is true or false, depending on whether the room is reserved or not. In the reservations schema, i have a column known as departure date.

So here is my question, when a room is reserved, i want to display a statement reading unavailable till ____ (1 day after the departure date in the reservation table). How can i accomplish that? I have already created the relationships.

Room.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Room extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'image', 'room_information', 'price', 'no_of_persons', 'reserved', 'hotel_id',
    ];

    /**
     * One to Many relationship with room
     *
     */
    public function hotel()
    {
        return $this->belongsTo('App\Hotel');
    }

    /**
     * Many to Many relationship with amenity
     *
     */
    public function amenities()
    {
        return $this->belongsToMany('App\Amenity');
    }

    /**
     * One to Many relationship with reservation
     *
     */
    public function reservations()
    {
        return $this->hasMany('App\Reservation');
    }

    /**
     *
     *
     */
    public function unreserved()
    {
        
    }


}

Reservation.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Reservation extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'reservation_no', 'client_name', 'client_email', 'arrival_date', 'departure_date', 'number_of_people', 'user_id', 'room_id', 'length_of_stay', 'total_cost',
    ];

    /**
     *
     * Boot the model
     *
     */

    public static function boot()
    {
        parent::boot();

        static::creating(function ($reservation) {
            $reservation->reservation_no = strtoupper('br') . "-" . strtoupper(Str::random(10));
        });
    }

    /**
     * One to Many relationship with user
     *
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }

    /**
     * One to Many relationship with room
     *
     */
    public function room()
    {
        return $this->belongsTo('App\Room');
    }
}

PageController.php (I need help on what to pass to the $departure variable)

 public function getRoomDetail($name)
    {
        $room = Room::where('name', '=', $name)->first();

        if ($room->reserved == true) {
            $day_after_departure = strtotime('+1 day', $departure);
        }

        
        //$room_by_location = Room::where('location',$room->location)->orderBy('created_at', 'desc')->paginate(3);
        $room_by_persons = Room::where('no_of_persons', $room->no_of_persons)->orderBy('created_at', 'desc')->get();
        $room_by_hotel = Room::where('hotel_id', $room->hotel_id)->orderBy('created_at', 'desc')->get();
        $room_by_price = Room::where('price', $room->price)->orderBy('created_at', 'desc')->get();
        return view('frontend.pages.rooms.room-detail', compact('room', 'room_by_hotel', 'room_by_persons', 'room_by_price'));
    }

0 likes
6 replies
martinbean's avatar

@toneymutinda Why does your Room model have a reserved flag? What happens if I reserve a room for 12 January 2019? Are you going to set that reserved flag to true and prevent people booking it until 13 January 2019?

Instead, use your has many relation to your Reservation model to determine if a room is reserved or not.

toneymutinda's avatar

Instead, use your has many relation to your Reservation model to determine if a room is reserved or not.

How can i achieve this?

martinbean's avatar
Level 80

How can i achieve this?

@toneymutinda Check if there is an associated Reservation model for a given date:

class Room extends Model
{
    public function reservations()
    {
        return $this->hasMany(Reservation::class);
    }

    public function isReservedOn(Carbon $dateTime)
    {
        // If a reservation has an arrival date equal to or less than the given date
        // and a departure date equal too or greater than the given date, then it is
        // reservered and therefore not available
        return $this->reservations()
                    ->where('arrival_date', '<=', $dateTime->toDateString())
                    ->where('departure_date', '>=', $dateTime->toDateString())
                    ->exists();
    }

    public function isReservedToday()
    {
        return $this->isReservedOn(Carbon::today());
    }
}
$reservedToday = $room->isReservedToday(); // Will return true or false

$nextYear = Carbon::now()->addYear();
$reservedNextYear = $room->isReservedOn($nextYear); // Will return true or false

If you want to show when a reservation on a given date ends, then you could do something like:

class Room extends Model
{
    //

    public function getReservationOn(Carbon $dateTime)
    {
        return $this->reservations()
                    ->where('arrival_date', '<=', $dateTime->toDateString())
                    ->where('departure_date', '>=', $dateTime->toDateString())
                    ->first();
    }
}
class RoomUnavailableException extends RuntimeException
{
    protected $until;

    public static function until(DateTime $until)
    {
        return (new static)->setUntil($until);
    }

    public function setUntil(DateTime $until)
    {
        $this->until = $until;

        return $this;
    }

    public function getMessage()
    {
        return sprintf('Room is booked until %s.', $this->until->toFormattedDateString());
    }
}
$reservation = $room->getReservationOn($someDate);

if ($reservation) {
    throw RoomUnavailableException::until($reservation->departure_date);
}

A single reserved column on your rooms table isn’t going to cut it as you won’t be able to see if the room’s currently reserved now, in a week, in a month, or in a year’s time.

Please or to participate in this conversation.