Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vkot91's avatar

How can i show only free rooms in Laravel

I am new in Laravel and doing hotel booking application,in position find room i try to checked dates from booking table(time_from and time_to) to show only free rooms.I think i have some mistakes in my Controller.I tried write whereRaw but it doesn't work too.Help me please

Its my FindRoomsController

<?php

namespace App\Http\Controllers\Admin;

use App\Room;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use App\Http\Controllers\Controller;
use Validator;

class FindRoomsController extends Controller
{
    public function index(Request $request)
    {
        if (!Gate::allows('find_room_access')) {
            return abort(401);
        }
        $time_from = $request->input('time_from');
        $time_to = $request->input('time_to');


        if ($request->isMethod('POST')) {
            $rooms = Room::with('booking')->whereHas('booking', function ($q) use ($time_from, $time_to) {
                $q->where(function ($q2) use ($time_from, $time_to) {
                    $q2->where('time_from', '>=', $time_to)
                       ->orWhere('time_to', '<=', $time_from);
                });
            })->orWhereDoesntHave('booking')->get();
        } else {
            $rooms = null;
        }

        return view('admin.find_rooms.index', compact('rooms', 'time_from', 'time_to'));
    }
}

My find room blade

@if (isset($rooms) && is_null($rooms))
            <div class="form-group" style="text-align: center">
                <label>@lang('quickadmin.find-room.no_rooms_found')</label>
            </div>
        @endif

   @foreach ($rooms as $room)
                        <tr data-entry-id="{{ $room->id }}">
                            <td></td>
                            <td field-key='room_number'>{{ $room->room_number }}</td>
                            <td field-key='floor'>{{ $room->floor }}</td>
                            <td field-key='description'>{!! $room->description !!}</td>
                            <td field-key='category_id'>{{ $room->category->name or ''}}</td>
                            <td field-key='price'>{!! $room->price !!}</td>
                            <td>
                                @can('booking_create')
                                    <button class="btn btn-danger">
                                        <a style="color: #ffffff;" href="{{ route('admin.bookings.create',
                                        ['room_id' => $room->id,'time_from' => $time_from, 'time_to' => $time_to]) }}">
                                            {!!trans('quickadmin.find-room.book_room')!!}</a>
                                    </button>
                                @endcan
                            </td>
                        </tr>
                    @endforeach

Booking table in database

if(! Schema::hasTable('bookings')) {
            Schema::create('bookings', function (Blueprint $table) {
                $table->increments('id');
                $table->datetime('time_from')->nullable();
                $table->datetime('time_to')->nullable();
                $table->integer('diff_days')->nullable();
                $table->text('additional_information')->nullable();
                $table->string('first_name');
                $table->string('last_name');
                $table->string('address')->nullable();
                $table->string('phone')->nullable();
                $table->string('email');
                $table->integer('all_price')->nullable();


                $table->timestamps();
                $table->softDeletes();

                $table->index(['deleted_at']);
            });
        }

Schema::table('bookings', function(Blueprint $table) {
                if (!Schema::hasColumn('bookings', 'room_id')) {
                $table->integer('room_id')->unsigned()->nullable();
                $table->foreign('room_id', '110461_5a676fa239ffd')->references('id')->on('rooms')->onDelete('cascade');
                }

        });

Room table in database

public function up()
    {
        if(! Schema::hasTable('rooms')) {
            Schema::create('rooms', function (Blueprint $table) {
                $table->increments('id');
                $table->string('room_number');
                $table->integer('floor')->nullable();
                $table->text('description')->nullable();
                $table->integer('price');
                $table->timestamps();
                $table->softDeletes();

                $table->index(['deleted_at']);
            });
        }
    }
0 likes
28 replies
Sinnbeck's avatar

So what is the problem? Wrong rooms? Wrong dates? Something else?

vkot91's avatar

I find room and create booking , and when i want to create new booking its show me this room again. I want service to check the date and dont show this room on this dates again

Sinnbeck's avatar

But I don't see any date in that query? Only a time? Is it a date time?

vkot91's avatar

Yes , its datetime in my controller. I tried to compare my dates and as a result i want it to show only free rooms, not booked.

Sinnbeck's avatar

My best bet is this is the wrong way around

$q2->where('time_from', '<=', $time_to)
                       ->orWhere('time_to', '>=', $time_from);
goldtaste's avatar

It's always a headache trying to do date queries, but think this should fix it:

        $rooms = Room::with('booking')->whereHas('booking', function ($q) use ($time_from, $time_to) {
                $q->where(function ($q2) use ($time_from, $time_to) {
                    $q2->where('time_from', '>=', $time_to)
                       ->where('time_to', '<=', $time_from);
                });
            })->orWhereDoesntHave('booking')->get();    
       

You want an and not an or in your time comparison.

Also, do you want >= or just > . You may end up with clashes on the day. Same goes for <=. But will leave it with you - my head hurts just thinking about it

vkot91's avatar

i try to do with $ or whereRow without $ and it's dont help me.When i have only 1 booking its dont show me room,but when i do 2 or more its against show me all rooms

goldtaste's avatar

Sorry, I'm not sure what you mean?

This part of the query :

$q2->where('time_from', '=>', $time_to)
                       ->orWhere('time_to', '<=', $time_from);

Should be

$q2->where('time_from', '=>', $time_to)
                       ->where('time_to', '<=', $time_from);

Do you mean you tried that and it didn't work?

Also you probably don't want to add the equals in to stop clashes on the day. So ideally it would be:

$q2->where('time_from', '>', $time_to)
                       ->where('time_to', '<', $time_from);
goldtaste's avatar

My amended query is basically saying

Get me booked rooms where the dates don't clash with the dates passed by the form

Or

The room doesn't have a booking

Is that what you are trying to achieve?

Simply put: get me all rooms that are booked after the passed in date AND get me all rooms that have bookings before the passed in date. So, it shouldn't return any where the dates clash.

vkot91's avatar

Yes,but when i write your code it's doesn't show me any rooms,even free

goldtaste's avatar

I notice that you have post check

if ($request->isMethod('POST')) {

}

Are you posting a form to the action?

goldtaste's avatar

I'll try running the code and see what's happening.

vkot91's avatar

i can sent you link on github

vkot91's avatar

Now it looks like , its doesn't show me room with active booking on any dates,not only on those dates that I reserved

Controller:

public function index(Request $request)
    {
        if (!Gate::allows('find_room_access')) {
            return abort(401);
        }
        $time_from = $request->input('time_from');
        $time_to = $request->input('time_to');


        if ($request->isMethod('POST')) {
            $rooms = Room::with('booking')->whereHas('booking', function ($q) use ($time_from, $time_to) {
                $q->where(function ($q2) use ($time_from, $time_to) {
                    $q2->where('time_to', '>', "time_from")->where('time_from', '<', 'time_to');
                });
            })->orWhereDoesntHave('booking')->get();
        } else {
            $rooms = null;
        }

My Blade:

<div class="panel panel-default">

        {!! Form::open(['method' => 'POST', 'route' => ['admin.find_rooms.index']]) !!}
        <div class="row" style="margin-top: 5px;">
            <div class="col-xs-9">
                <div class="col-xs-6 form-group">
                    {!! Form::label('time_from', trans('quickadmin.bookings.fields.time-from').'*', ['class' => 'control-label']) !!}
                    {!! Form::text('time_from', old('time_from'), ['class' => 'form-control datetimepicker', 'id'=>'txtFrom','placeholder' => '', 'required' => '']) !!}
                    <p class="help-block"></p>
                    @if($errors->has('time_from'))
                        <p class="help-block">
                            {{ $errors->first('time_from') }}
                        </p>
                    @endif
                </div>
                <div class="col-xs-6 form-group">
                    {!! Form::label('time_to', trans('quickadmin.bookings.fields.time-to').'*', ['class' => 'control-label']) !!}
                    {!! Form::text('time_to', old('time_to'), ['class' => 'form-control datetimepicker','id'=>'txtTo', 'placeholder' => '', 'required' => '']) !!}
                    <p class="help-block"></p>
                    @if($errors->has('time_to'))
                        <p class="help-block">
                            {{ $errors->first('time_to') }}
                        </p>
                    @endif
                </div>
            </div>

            <div class="col-xs-2">
                <div class="form-group" style="margin-top: 5px;">
                    <label class="control-label"></label>
                    {!! Form::submit('Search for rooms', ['class' => 'btn btn-danger btn-block']) !!}
                    {!! Form::close() !!}
                </div>
            </div>
        </div>
        @if (!is_null($rooms))
        <div class="panel-body table-responsive">
            <table class="table table-bordered table-striped">
                <thead>
                <tr>
                    <th/></th>
                    <th>@lang('quickadmin.rooms.fields.room-number')</th>
                    <th>@lang('quickadmin.rooms.fields.floor')</th>
                    <th>@lang('quickadmin.rooms.fields.description')</th>
                    <th>@lang('quickadmin.rooms.fields.category')</th>

                    <th>Price per Night</th>
                </tr>
                </thead>
                <tbody>
                    @foreach ($rooms as $room)
                        <tr data-entry-id="{{ $room->id }}">
                            <td></td>
                            <td field-key='room_number'>{{ $room->room_number }}</td>
                            <td field-key='floor'>{{ $room->floor }}</td>
                            <td field-key='description'>{!! $room->description !!}</td>
                            <td field-key='category_id'>{{ $room->category->name or ''}}</td>
                            <td field-key='price'>{!! $room->price !!}</td>
                            <td>
                                @can('booking_create')
                                    <button class="btn btn-danger">
                                        <a style="color: #ffffff;" href="{{ route('admin.bookings.create',
                                        ['room_id' => $room->id,'time_from' => $time_from, 'time_to' => $time_to]) }}">
                                            {!!trans('quickadmin.find-room.book_room')!!}</a>
                                    </button>
                                @endcan
                            </td>
                        </tr>
                    @endforeach
                @endif
                </tbody>
            </table>
        </div>
    </div>
vkot91's avatar

It's dont work,or maybe i write something wrond in my code

goldtaste's avatar

My code was wrong. Turns out it is actually a pretty complicated query. I'll let you know if I figure it out.

vkot91's avatar

Thank you man,i'll wait for your answer,because it very important for me

goldtaste's avatar
Level 8

Okay, haven't given this much testing. But I think it may work. Though, needs lots of testing:

$rooms = App\Room::whereNotIn('id', function($query) use ($time_from, $time_to) {
       $query->from('bookings')
        ->select('room_id')
        ->where('time_from', '<=', $time_to)
        ->where('time_to', '>=', $time_from);
    })->get();

If you get an error try replacing bookings with just booking:

$query->from('booking')

Good luck

vkot91's avatar

I get this error

InvalidArgumentException
Illegal operator and value combination.
goldtaste's avatar

Can you post your controller code?

And does it say what line on the controller the error is thrown.

Cheers

vkot91's avatar
class FindRoomsController extends Controller
{
    public function index(Request $request)
    {
        if (!Gate::allows('find_room_access')) {
            return abort(401);
        }
        $time_from = $request->input('time_from');
        $time_to = $request->input('time_to');


        if ($request->isMethod('POST')) {
              $rooms = Room::whereNotIn('id', function($query) use ($time_from, $time_to) {
            $query->from('bookings')
                ->select('room_id')
                ->where('time_from', '>=', $time_to)
                ->where('time_to', '<=', $time_from);
        })->get();
        } else {
            $rooms = null;
        }


        return view('admin.find_rooms.index', compact('rooms', 'time_from', 'time_to'));
    }
}

goldtaste's avatar

What happens if you change

$query->from('booking')

to

$query->from('bookings')

Did that throw an error?

vkot91's avatar

Sorry, i write

 ->where('time_from', '>=', $time_to)
                ->where('time_to', '<=', $time_from);

But you write

  ->where('time_from', '<=', $time_to)
                ->where('time_to', '>=', $time_from);

Everythink is work now Thank you very much ,you are the best

goldtaste's avatar

No worries. like I mentioned, you will probably want to do a lot of testing, as I did just a couple of quick tests.

1 like
vkot91's avatar

By the way, are you know how i can finding the difference between this two dates and saving the result to database?

Please or to participate in this conversation.