whereMonth failing to retrieve appointment dates by month - php

I have two models in my application, Appointment and Date, an appointment has many dates and a date belongs to an appointment, now I want to search for appointments with dates which were created in a specific month, I do this by looking at appointments with dates, where this dates fullDate field is equal to the passed month, I use eloquent whereMonth for this.
Sadly the functions returns no results despite being results, I suspect this might be because Date model fullDate field is a string instead of a timestamp so maybe that's why it's failing, I tried casting fullDate to timestamp but I'm getting the same results.
fullDate is a string like this: "26-3-2020".
This is my controller method:
public function list2(Request $request)
{
$month = $request->input('month');
$appointments = Appointment::whereHas('dates', function ($query) use ($month){
$query->whereMonth('fullDate', $month);
})->with(['user'])->latest()->paginate($request->input('paginate'));
}
Date model migrations:
public function up()
{
Schema::create('dates', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('appointment_id')->index();
$table->foreign('appointment_id')->references('id')->on('appointments')->onDelete('cascade')->onUpdate('cascade');
$table->string('fullDate');//34-3-2020
$table->timestamps();
});
}
Any idea why it's failing.

fullDate column type should be timestamp,
and you should add this in the Date model:
protected $dates = [
'fullDate',
];

Related

Laravel 6 query same table with different where clause

I have campaign_report table like this
Schema::create('campaign_report', function (Blueprint $table) {
$table->bigIncrements('id');
$table->date('report_date');
$table->bigInteger('user_id');
$table->bigInteger('campaignId');
$table->double('cost',12,2);
$table->timestamps();
});
I am trying to get all yesterday's campaign reports.
$campaignReports = CampaignReport::where(['report_date' => "$yesterday", 'user_id' => Auth::user()->id])->orderBy('report_date', 'desc')->paginate(25);
Above query is returning all campaigns where report_date is equal to $yesterday.
Along with this query I also want to get the cost value of each campaign where report_date is day before yesterday matching the campaignId column. I want to show the difference of cost between yesterday's campaigns and day before yesterday's campaigns.
like
foreach($campaignReports as $campaignReport)
{
$difference = $campaignReport->cost - $campaignReport->dayBeforeYesterdayCost;
}
Can anyone help me in building this query using Query Builder or Eloquent?
You can write a relation in your CampaignReport model that calculate difference between yesterday's cost and the day before that
public function dayBeforeYesterdayCost() {
$dayBeforeYesterday = Carbon::parse($this->report_date)->subDays(1); //return date of day before yesterday
$dayBeforeYesterdayCost = CampaignReport::where('campaignId', $this->campaignId)
->where('report_date', $dayBeforeYesterday)
->first();
return $dayBeforeYesterdayCost ? $dayBeforeYesterdayCost->cost : 0;
}
public function lastDayDifference() {
$difference = $this->cost - $this->dayBeforeYesterdayCost;
return $difference;
}
Now you can return $campaignReports with lastDayDifference relation like this:
$campaignReports = CampaignReport::where(['report_date' => "$yesterday", 'user_id' => Auth::user()->id])
->with('lastDayDifference')
->orderBy('report_date', 'desc')
->paginate(25);
At the end you have one object attached to your every single $campaignReport
Group by date(report_date) which will just give you the date part, order by the same descending, then just take the values for yesterday and the day before. Something like:
CampaignReport::select(DB::raw('date(report_date) report_date', DB::raw('count(*) as count'))
->where('report_date','>=',$twoDaysAgo)
->where('user_id', Auth::user()->id])
->groupBy('report_date')
->orderBy('report_date', 'desc');

Laravel Eloquent get where doesnt have, search where has when not null

This question is really hard to word, so I apologise for the title!
Lets say I have a Rooms model and a Bookings model, 1 room can have many bookings.
I am building a table with filters, and I need to be able to run a filter on the booking relationship IF there is a booking, else grab the record anyway.
Lets say my room has a booking relationship like so
public function latestBooking(){
return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
->orderBy('expiry_date', 'DESC')->limit(1);
}
The above relationship gets me the latest booking.
I'm running a 'vacant from' filter like so
if ($request->has('filters.vacant_from')) {
$rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
$query->where('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
});
}
The issue is that this only gets rooms that have a booking and are available after the date specified. I need it to be able to search all rooms, if it does have a booking, check if the expiry date is after the date specified, if it doesn't have a latest booking, get it anyway as its a vacant room.
Basically how would I structure my filter function so that it runs like this
Search all rooms, if it has a latest booking, check its expiry date is after the date specified and only grab it if its true/vacant, if it doesn't have a latest booking then grab it anyway as it is vacant
I have a suggestion for you regarding your latestBookingRelationship. You should create another relationship and add a greater than today condition to it and maybe name it activeLatestBooking.
Then, your latest Booking should comprise all booking rooms irrespective of whether their booking is active or not.
public function activeLatestBooking(){
return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
->where('expiry_date', '>', date('d/m/Y', strtotime('today')))->orderBy('expiry_date', 'DESC')->limit(1);
}
public function latestBooking(){
return $this->hasOne('App\Models\Bookings', 'room_id', 'id')
->orderBy('expiry_date', 'DESC')->limit(1);
}
Then, to answer your question:
if ($request->has('filters.vacant_from')) {
$rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
$query->where('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
})->orWhereDoesntHave('latestBooking');
}
What the filter query does is this: It gets all latest bookings whose expiry_date is less than the vacant_from date...and the orWhereDoesntHave gets all rooms that have never been booked.
the booking relationship should be like this,
public function latestBooking(){
return $this->hasMany('App\Models\Bookings')->orderBy('expiry_date', 'DESC');
}
as this is a one to many relationship. laravel relationship
and you can write your filter like this,
if ($request->has('filters.vacant_from')) {
$rooms = $rooms->whereHas('latestBooking', function ($query) use ($request) {
$query->whereDate('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
});
}
you can use whereDate to run date queries in laravel. Hope this helps
Assuming you have hasMany relation between Rooms and Bookings model with name bookings
$rooms = Rooms::whereHas('bookings', function ($query) use ($request) {
$query->whereDate('expiry_date', '<', Carbon::createFromFormat('d/m/Y',$request->input('filters.vacant_from'))->format('Y-m-d'));
})->orWhereDoesntHave('bookings')->get();

timestamp changing without modifyng the field in the db

I'm having a problem with my 'end_date' column on my database. First off, I'm making a To-do application. So I have a table called 'Tasks' with following Columns:
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->mediumText('description');
$table->timestamp('end_date');
$table->integer('completed');
$table->timestamps();
When a user creates a task they can give an end_date to this task. I'm in the UTC+2 timezone so for the user I'm displaying all times in UTC+2 but i'm storing them in UTC on my database.
Here are the input fields with the actual Store function:
{{Form::date('end_date', \Carbon\Carbon::now()->timezone('Europe/Brussels'),['class' => 'form-control mb-2 mr-sm-2 mb-sm-0'])}}
{{Form::time('time', \Carbon\Carbon::now()->timezone('Europe/Brussels')->format('H:i'),['class' => 'form-control'])}}
Because I'm using 2 input fields I have to merge them together in the store function:
public function store(Request $request)
{
$requestData = $request->all();
$task = new Task($requestData);
$inputDateAndTime = $requestData['end_date'].' '.$requestData['time'].':00';
$task['end_date'] = Carbon::createFromFormat('Y-m-d H:i:s', $inputDateAndTime, 'Europe/Brussels')->timezone('UTC');
$task['user_id'] = auth()->id();
$task['completed'] = 0;
$task->save();
return redirect('/tasks')->with('success', 'Task created');
}
In this function I specify that the user has given a Time in UTC+2 timezone and I want this to be converted in UTC. (This works as expected)
The problem: So if the user wishes to complete this task, they can do a PUT request to update the 'completed' column, But when this request is being handled my end_date column is being changed on the same time without touching the column at all.
My update function:
public function update(Request $request, Task $task)
{
$task -> completed = 1;
$task->save();
return redirect('/tasks')->with('success', 'Task completed');
}
Example of the problem:
Let us say that user 1 creates a task with following end date = 08/18/2018 20:14
Note that this time is for UTC+2, so I'm saying convert this to UTC.
After the store function, I check the database, with following end_date = 2018-08-18 18:14:00
Which is correct, now lets see what my end_date is when I run the update function:
public function update(Request $request, Task $task)
{
dd($task->end_date);
// the result:
Carbon #1534616040 {#552 ▼ date: 2018-08-18 18:14:00.0 utc(+00:00)
}
}
So still the same value, but If I run the update function as normal and check the database this is my value:
2018-08-18 17:24:27, what I noticed is that my updated_at field has the same last 2 digits, so it is somehow taking the current time I would assume. My updated_at field: 2018-08-18 15:24:27
Any idea what I'm doing wrong here?
Timestamp is controlled by the db do that when a record is updated, it will reflect that. To have a custom field that only changes when you want it to, use datetime.

Getting specific date ranges from database in Laravel

I need to get results from a DB divided by dates such as today, yesterday, this week, last week, etc.
I can easily do this with whereRaw and some SQL:
whereRaw('Date(created_at) = CURDATE()')->get();
I wonder if there is an easier, proper way to do this with Eloquent.
You could create a scope for a particular class like this:
public function scopeYourQuery($query, $user) {
return $query->where('user_id', $user->id)->orderBy('created_at', 'desc')->first();
}
This just gets the first item of a descending ordered list ordered by created_at date per user.
If you wanted something that was between date ranges? You just pass in your date and extend it a bit with some PHP, maybe something like this would work:
public function scopeSomeDateQuery($query, $fetch_date, $user)
{
//clone the users chosen month - so we can make the range until the following month
$also_fetch_date = clone $fetch_date;
$next_month = $also_fetch_date->addMonth();
$next_month = $next_month->format('Y-m-d');
$fetch_date = $fetch_date->format('Y-m-d');
//return the query for the monthname
return $query->orderBy('created_date')->where('created_date', '>=', $fetch_date)->where('created_date', '<', $next_month)->where('user_id', $user->id);
}
This would look in a monthly range (per user) to get an ordered list of items with a created_date in that range.

Laravel compare between date field and date now

I am trying to compare between date field that saved to my database and current date!
The circle is:
admin will add a new career with deadline date
when someone fill the application he/she will see the available jobs only in drop down list ( that its deadline date less than the current date )
so this is the Jobs model
protected $fillable = ['job_name','job_req', 'expire'];
this is jobs migrations
public function up()
{
Schema::create('jobs', function(Blueprint $table)
{
$table->increments('id');
$table->string('job_name');
$table->string('job_req');
$table->date('expire');
$table->timestamps();
});
}
public function down()
{
Schema::drop('jobs');
}
this is the ApplicationController.php
public function create()
{
$dt = Carbon::now()->toDateString();
$jobs = Jobs::get()->where('$dt', '<', 'expire');
return view('post.create',compact('jobs'));
}
Now when i open application form it doesn't returns any job title, but when i remove where clause from the controller it works well!
change
$jobs = Jobs::get()->where('$dt', '<', 'expire');
to
$jobs = Jobs::where('expire', '>', $dt)->get();
->get() will do query instantly, you must use ->where() before it.
Use ->where after ->get(), you will call this function
http://laravel.com/api/5.1/Illuminate/Database/Eloquent/Collection.html#method_where

Categories