Laravel query builder inject column value into Carbon query - php

I've got a query that I'm running in my project on a model called Domain, it returns all domains where the status column of a domain matches complete and a date column is before or equal to a specific set of days.
I've recently refactored the model columns and have included a new column called domain_alert_period which is an integer column that holds a value in days, I need to somehow target this column and put it in replace of my existing 30 so that the user is able to control the number of days prior to getting an alert.
What am I missing from this to achieve this?
return Domain::where('status', 'complete')
->where(function ($sql) {
$sql->where('domain_expires_on', '>', Carbon::now()->subDays(2)) // 2 days after expiry
->where('domain_expires_on', '<', Carbon::now()->addDays(30)); // 30 days before expiry
})
->get();

I believe you can use whereRaw() in your clause to use raw DB expressions, If its MySQL you can use DATE_ADD method with your column value for comparision
$sql->where('domain_expires_on', '>', Carbon::now()->subDays(2)) // 2 days after expiry
->whereRaw('domain_expires_on < DATE_ADD(NOW(), INTERVAL domain_alert_period DAY)');

A mysql DATE_SUB function should be used to subtract days from a domain_expires_on date. so that will be a date you should start an alert from
And then match a current date is greater or equal to that alert date
$query = $this->model
->whereRaw('CURDATE() <= DATE_ADD(`domain_expires_on` , INTERVAL 2 DAY)') // till 2 days after expiry
->whereRaw('CURDATE() >= DATE_SUB(`domain_expires_on` , INTERVAL domain_alert_period DAY)')
->get();

If i understand your question correctly what you can do is use use ($var) in your query to replace 30
$start=1; //you can also take date from user for between like `date_from` and `date_to` and parse them with Carbon insted of adding or substracting days from now()
$end=30;
return Domain::where('status', 'complete')
->where(function ($sql) use ((int) $start,(int) $end) {
$sql->whereDate('domain_expires_on', '>', Carbon::now()->subDays($start)->toDateString())
->whereDate('domain_expires_on', '<', Carbon::now()->addDays($end)->toDateString());
})
->get();
Also if you are storing domain_expires_on only as the date you should format the carbon date to match your database format.
above method will work for $table->date('domain_expires_on'); and $table->dateTime('domain_expires_on');

Related

How to add days in querying date? laravel

How can we add days in the date that we're querying using laravel eloquent?
Something like this:
Post::where('created_at + 7 days', now()->toDateTimeString())
->where('created_at', '<', now()->toDateTimeString())
->get();
My logic is like this one
today >= created_at && today <= created_at + 4
Is there some correct syntax to achieve this one?
One of the ways to compare from date time is using the calculated Carbon like below:
Post::where('created_at', '>=', now()->addDays(4)->toDateTimeString()
->get();
It will display only posts which have created_at greater than 4 days from today.
For date range filter, you can use between scope like:
$startDate = now()->subDays(4)->toDateString();
$endDate = now()->toDateString();
$filteredPosts = Post::whereBetween('created_at', [$startDate, $endDate])->get();
For more information about filter, you could visit Laravel Query Builder
You can use whereDate method:
Post::whereDate('created_at', 'like', now()->subDays(4))->get();
or
Post::whereDate('created_at', '>=', now()->subDays(4))->get();

How to query between two x amount of days using Laravel and Carbon?

I'm trying to retrieve data from the past 30 to 60 days. Which means I'm leaving out days 0 to 30 and everything past day 60.
My current progress is as such:
$previousMonth = DB::table('table')
->select('table.*')
->whereBetween('date', [Carbon::now()->subDays(30), Carbon::now()->subDays(60)])
->get();
return $previousMonth;
"date" has the datatype of DATETIME in mysql database.
Change the order, because Carbon::now()->subDays(30) is greater than Carbon::now()->subDays(60), and you can use startOfDay() to get start of day:
->whereBetween('date', [Carbon::now()->subDays(60)->startOfDay(), Carbon::now()->subDays(30)->startOfDay()])
Try this startOfDay()
use Carbon\Carbon;
$previousMonth = DB::table('table')
->select('table.*')->whereBetween('date', [Carbon::now()->subDays(60)->startOfDay(), Carbon::now()->subDays(30)->startOfDay()])->get();
return $previousMonth;
Refer This Link
http://carbon.nesbot.com/docs/

Check the year of timestamps [duplicate]

This question already has answers here:
How to compare timestamp dates with date-only parameter in MySQL?
(11 answers)
Closed 3 years ago.
I have stored timestamps in my database. Timestamps like 483753600, 799286400, etc.
I would like to check if the year 2015 would match with any of my timestamps.
The only way that I know that I could do it, would be getting ALL the timestamps from the database and then check the year of each timestamp with getdate(799286400)['year']. That would be a solution but it's way too bad for the performance! Is there any other softer way to do this?
Update
This is what I have tried so far:
public function dateOfBirth(string $year): array {
return $query = $this->createQueryBuilder('p')
->select('p.uid')
->where("p.dateOfBirth BETWEEN :start AND :end")
->setParameter('start', "$year-01-01")
->setParameter('end', "$year-01-01")
->getQuery()
->getResult();
}
but it returns an empty array.
It looks like you are storing epoch timestamps. To check for timestamps that belong to year 2015, an efficient method would be to generate a range of epoch timestamp that represent the year boundaries, and then compare it to the stored values. Assuming that timestamps are stored in column col:
select exists (
select 1
from mytable
where col >= unix_timestamp('2015-01-01') and col < unix_timestamp('2016-01-01')
) as exists_year_2015
This query will give you a unique record, with a unique column containing a boolean value (0/1) that indicates if any record in the table has a timestamp that belongs to year 2015.
Such an expression will be able to take advantage of an index on the timestamp column.
You have a couple of problems with your code, first of all you are returning an assignment
return $query = $this->createQue...
also you set the same parameter value to both :start and :end, the string "$year-01-01" which will not match the stored timestamps, and you don't change the value of $year in between so even if it could match it would be an empty range.
You need to determine the starting and ending timestamp for the given year and use them as parameters for the query.
public function dateOfBirth(string $year): array {
// get the DateTimes
$startDate = new \DateTime("midnight January 1, $year");
$year += 1;
$endDate = new \DateTime("midnight January 1, $year");
// get the timestamps
$start = $startDate->format('U');
$end = $endDate->format('U');
return $this->createQueryBuilder('p')
->select('p.uid')
->where("p.dateOfBirth > :start")
->andWhere("p.dateOfBirth < :end")
->setParameter('start', $start)
->setParameter('end', $end)
->getQuery()
->getResult();
}

PHP Carbon / Laravel Eloquent - Check if DateTime value is for the current day

I am working on a booking system and need to select only the records where a certain field is for today. Not today and in the future, but only today.
The query currently is:
$advancedBookings = Booking::where('type', 2)
->whereNull('estimated_booking_time')
->where('requested_booking_time', ?????);
$advancedBookings->get();
The requested_booking_time is the field that I wish to be checked, the date stored is in this format:
2017-08-23 08:00:00
So I want to only select rows that are on the same day as the current day.
As i understand, you want that records which is created today; then just get the today's date.
$today = date("Y-m-d");
now your query is like this.
$advancedBookings = Booking::where('type', 2)
->whereNull('estimated_booking_time')
->where('requested_booking_time', $today)->get();
You can use whereDate and format your dates with Carbon:
$advancedBookings = Booking::where('type', 2)
->whereNull('estimated_booking_time')
->whereDate('requested_booking_time', '=' , Carbon::today()->toDateString());
$advancedBookings->get();
Or format the your date before the query with Carbon.
You should try this:
$advancedBookings = Booking::where('type', 2)
->whereNull('estimated_booking_time')
->whereDate('requested_booking_time', '=', date('Y-m-d'))
->get();

Laravel - Get row that has today between begin and end

I have a table that has two dates fields, begin and end.
I'm trying to get all rows that have begun but not yet ended. and if today is less than begin, they shouldn't be included. and if today is grater than end they shouldn't be included.
I'm using laravels eloquent. Here is what i've tried
$now = \Carbon\Carbon::now();
$promos = \App\Models\LivePromo::
where("begin", "<=", $now)
->where("end", ">=", $now)
//Other conditions
->get();
This seemingly work, but it also selects rows that are greater have already ended.
How can i make this work as i expect?
EDIT
The begin column is a datetime column that signifies when the 'promo' should start, and the end column is a datetime column that signifies when the 'promo' should end. I'm just trying to get all valid promos for the current date and time
EDIT
Sample data
$now = '2017-02-24 10:29:10' // \Carbon\Carbon::now();
remove = from end date condition:
$now = \Carbon\Carbon::now();
$promos = \App\Models\LivePromo::
where("begin", "<=", $now)
->where("end", ">", $now)
->get();
Also, it might depend on your database engine.
Some engines require you to use the whereDate() method instead of plain old where()
$promos = LivePromo::whereDate("begin", "<=", $now)
->whereDate("end", ">", $now)
->get();

Categories