Laravel - Get data last 24 hours, 1 week or 1 month - php

So I'm trying to grab only data which are in last 24 hours, 1 week, 1 month. I have working code, but if I get it correctly it's "other way". By that I mean, If date is at the moment 30-Nov-2016 and I set the Data value to 1-Dec-2016, then the 24 Hour one still grabs the information, but it shouldn't. If date is 30-Nov-2016 and I set it to 28-Nov-2016, then the 24 Hour one doesn't grab it. For me It sounds like it's backwards. I hope the explanation is understandable.
$getItemsOneDay = Deposit::where('steam_user_id',0)->where('status', Deposit::STATUS_ACTIVE)->where('created_at', '>', Carbon::now()->subMinutes(1440))->get();
$getItemsOneWeek = Deposit::where('steam_user_id',0)->where('status', Deposit::STATUS_ACTIVE)->where('created_at', '>', Carbon::now()->subMinutes(10080))->get();
$getItemsOneMonth = Deposit::where('steam_user_id',0)->where('status', Deposit::STATUS_ACTIVE)->where('created_at', '>', Carbon::now()->subMinutes(43200))->get();

You wrote created_at > time.
So you ask laravel to search all data greater than now(). So you look into the future.
Either you want to...
look at points before a certain point in time: created_at < time
look at points after a certain point in time: created_at > time
look at points within an interval of passed time: created_at > start && created_at < end
If i got you right you are searching for the third option. So you need to do something like ...->where("created_at",">",Carbon::now()->subDay())->where("created_at","<",Carbon::now())->...
Hopefully, I got you right here.

->where('created_at', '>=', Carbon::now()->subDay()->toDateTimeString())->get();
to get the data created within last 24 hours

Check the below function; it is working fine.
public function getanswer_24hours(Request $request)
{
$ans = Answer::where('user_id',$request->user_id)->where('created_at', '>=', Carbon::now()->subDay()->toDateTimeString())->get();
if(count($ans) > 0)
{
$result = 'yes';
return response()->json(['data' =>['answer' => $ans,'result' => $result, 'message' => 'get Answer Before 24hours SuccessFully!!','status' => true],200,'ok']);
}else{
$result = 'no';
return response()->json(['data' =>['answer' => [], 'result' => $result, 'message' => 'get Answer Failed!!'],404,'no']);
}
}

Related

Laravel query builder inject column value into Carbon query

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');

PHP Check for time differences

I'm looking for a lean way to compare two times. One is the time, someone requested a new password(FOS UserBundle provides a Getter for that) and the other is the current time minus e.g. 10 minutes.
if($user->getPasswordRequestedAt() <= date("Y-m-d H:i:s", strtotime('-10 minutes'))){
return $this->render('#User/Resetting/no_resend.html.twig', array( 'username' => $username));
}
else {
return $this->render('#User/Resetting/check_email.html.twig', array(
'tokenLifetime' => ceil($this->container->getParameter('fos_user.resetting.retry_ttl') / 60),
));
So if someone requested a password already 10 minute ago, he gets to the page saying "You already requested a password, please wait 10 minute to retry.". If the request was longer than 10 minutes ago, the pages says "Email for password reset has been sent".
I would think the comparison is right that way but it's somehow always going to the "else" part.
Where's the mistake?
if($user->getPasswordRequestedAt() >= date("Y-m-d H:i:s", strtotime('-10 minutes'))){
Should do the trick.
Since you want to check if the last request was done in the last 10 minutes or newer
As far as I know $user->getPasswordRequestedAt() (since being processed through Doctrine) is an instance of \DateTime.
So use another datetime to compare it:
$limit = \new DateTime();
$limit->sub(new \DateInterval("P600S"));
if($user->getPasswordRequestedAt() >= $limit){
return $this->render('#User/Resetting/no_resend.html.twig', array( 'username' => $username));
}
else {
return $this->render('#User/Resetting/check_email.html.twig', array(
'tokenLifetime' => ceil($this->container->getParameter('fos_user.resetting.retry_ttl') / 60),
));
With this you keep the OOP style and have a clean if clause. The $limit holds a timestamp from 10 minutes ago. So when you requested your password at 14:10 and it is 14:19 by now, $limit will hold 14:09. As long as the requested password date is bigger than the timestamp 10 minutes ago, there won't be a resend.
EDIT: Since you are using the FOS UserBundle it is indeed possible to make it even shorter as iainn pointed out:
if($user->isPasswordRequestNonExpired(600)){
return $this->render('#User/Resetting/no_resend.html.twig', array( 'username' => $username));
}
else {
return $this->render('#User/Resetting/check_email.html.twig', array(
'tokenLifetime' => ceil($this->container->getParameter('fos_user.resetting.retry_ttl') / 60),
));
The first and only argument of this method is a amount of seconds that have to pass so that the password can be requested again.
Since I haven't used symfony I can't know for sure.
But this is my guess. See if it works.
$dt = $user->getPasswordRequestedAt();
If($dt->getTimestamp() <= strtotime(time())-600){
return $this->render('#User/Resetting/no_resend.html.twig', array( 'username' => $username));
}else {
return $this->render('#User/Resetting/check_email.html.twig', array(
'tokenLifetime' => ceil($this->container->getParameter('fos_user.resetting.retry_ttl') / 60),
));
This will create the datetime object to $dt variable.
In the if() I use get_timestamp to get the Unix value of the datetime object and compare it to Unix time -600 seconds (10 minutes).
The reason I choose Unix values is because they are great for comparison.

MySQL how to create timestamp from year (argument), weekOfYear (argument), time (database) and dayofweek (database)?

I need to implement showing of some events on an existing project. I can not change database structure.
In my controller I get passed (from ajax request) a timestamp and I need to show previous 8 events. So if timestamp is (converted) 2017-12-12 00:00:00 I need to show 8 events before 2017-12-12, ordered by their time DESC.
This is how my table is set up:
-calendarrepeat
-dayofweek // int 1-7; 1 = monday, 7 = sunday
-event_date_begin // date "2016-05-01" - indicates from which day the event recurrs every week (dayofweek)
-event_date_end // date "2017-05-02" - indicates until which day the event recurrs every week (dayofweek)
-event_hour_begin // time "11:00:00"
-event_hour_end // time "12:00:00"
I can do whatever I want with the timestamp. I use Carbon so it's not a problem to get week of the year, day of the year or whatever else I would need.
For reference $fullTs is the timestamp I get passed into the controller. The join part works fine.
The part I need help with is: /* THIS PART has to be rewritten (it's COMPLETELY wrong at the moment) ! */
I need to generate timestmap from year (passed as argument), weekOfYear (passed as argument), day of week (from database column) and time (database column). I would need something like this instead (pseudoSQL):
->where(\DB::raw('THISTHINGY_TO_DATE($fullTs->year $fullTs->weekOfYear calendarrepeat.dayofweek calendarrepeat.event_hour_begin, "%Y %week-of-year %day-of-week %H:%i:%s), '<', $fullTs)))
This is the full query I'm currently running (the first part of UNION, the second one works as intended):
$eventsRepeat = CalendarRepeat::join('calendarrepeat_translations', function ($j) use ($locale) {
$j->on('calendarrepeat.id', '=', 'calendarrepeat_translations.calendarrepeat_id')
->where('calendarrepeat_translations.locale', '=', $locale);
})
->orderBy('calendarrepeat.event_date_begin', $orderBy)
/* THIS PART has to be rewritten (it's COMPLETELY wrong at the moment) ! */
/* the STR_TO_DATE(..) part has to get date from a) week passed in $fullTs b) dayoftheweek written in calendarrepeat.dayoftheweek c) time written in calendarrepeat.event_hour_begin */
->where(\DB::raw("STR_TO_DATE(CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin), '%Y-%m-%d %H:%i:%s')"), '<', $fullTs)
->where('event_date_begin', '>', $fullTs)
->where('event_date_end', '<', $fullTs)
->limit(8)
->select([
'calendarrepeat.event_date_begin as date', 'calendarrepeat.event_hour_begin as start',
'calendarrepeat.event_hour_end as end', 'calendarrepeat_translations.title as title', \DB::raw("CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin) as date_whole") // This is also wrong
]);
Is that possible? How? Is there a better way to go about doing this?
Another thing to be careful about is that in our DB 1 = monday, 7 = sunday, which from my understanding isn't a common way to enumerate week days.
Thanks in advance.
Try this and check the result you have got:
$eventsRepeat = CalendarRepeat::join('calendarrepeat_translations', function ($j) use ($locale) {
$j->on('calendarrepeat.id', '=', 'calendarrepeat_translations.calendarrepeat_id')
->where('calendarrepeat_translations.locale', '=', $locale);
})->select([
'calendarrepeat.id',
'calendarrepeat_translations.calendarrepeat_id',
'calendarrepeat_translations.locale','calendarrepeat.event_date_begin as date',
'calendarrepeat.event_hour_begin as start',
'calendarrepeat.event_hour_end as end',
'calendarrepeat_translations.title as title',
\DB::raw("CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin) as date_whole")
])->where(\DB::raw("STR_TO_DATE(CONCAT(date, ' ', start), '%Y-%m-%d %H:%i:%s')"), '<', $fullTs)
->where('date', '>', $fullTs)
->where('end', '<', $fullTs)
->orderBy('date', $orderBy)
->limit(8);

Laravel Trends with Carbon Based on Rating

I want to find out if a product is trending on my website (trending up or down) based on the period that is passed in. I.e. If week is passed in, it compares the current week up to the day to the previous week up to the same day.
e.g. If today is Wednesday, and the mode is week, it will compare this week up to today, with last week up to last Wednesday.
I have so far:
public function getTrendAttribute($period)
{
$last_period = $this->ratings()->where(DB::raw(), )->avg('rating');
$this_period = $this->ratings()->where(DB::raw(), )->avg('rating');
}
Which I don't think is the correct start :(.
How can I achieve this (I have the Carbon library in my app)?
What about this? I am not sure if it is very efficient but it seems to be giving me some numbers that make sense:
public function getTrendAttribute($period)
{
$tz = 'Europe/London';
$this_week_start = Carbon::now($tz)->startOfWeek();
$now = Carbon::now($tz);
$last_week_start = Carbon::now($tz)->subWeek(1)->startOfWeek();
$now_last_week = Carbon::now($tz)->subWeek(1);
$last_period = $this->ratings()->where('created_at', '>=', $last_week_start)->where('created_at', '<=', $now_last_week)->avg('rating');
$this_period = $this->ratings()->where('created_at', '>=', $this_week_start)->where('created_at', '<=', $now)->avg('rating');
return $last_period > $this_period ? -1 : $last_period < $this_period ? 1 : 0;
}
Try this. Note that it is specific to the week grouping, and you would have to modify that query for grouping by month, or day, or anything else like that. But you should be able to use MySQL date functions to accomplish this.
$last_period = $this->ratings()->where(DB::raw('week(created_at)'), DB::raw('week(now()) - 1'))->where(DB::raw('dayofweek(created_at)'), '<=', DB::raw('dayofweek(now())'))->avg('rating');
$this_period = $this->ratings()->where(DB::raw('week(created_at)'), DB::raw('week(now())')->avg('rating');

Querying Data and Grouping by Day with Laravel

I run a website that stores images and users get a hotlink.
I want to be able to query records made in the last 7 days in the table containing the uploaded image data, extract the created_at column only, and compile the data into an array, similar to making an archive list for a blog.
I would like for the results to be presented like:
[
'Sunday' => 5,
'Monday' => 45,
'Tuesday' => 452,
...
]
Where each number represents the number of records created on each day. As long as I can output an array like that, I can handle the Javascript side easily.
Anybody have any suggestions?
EDIT
This is the code I've tried so far:
<?php
class Admin
{
public function getCreatedAtAttribute($value)
{
$this->attributes['created_at'] = Carbon::createFromFormat('Y-m-d H:i:s', $value);
}
public static function uploadsGraph()
{
$date = \Carbon\Carbon::now();
$uploads = Upload::select('created_at')->where('created_at', '>=', \Carbon\Carbon::now()->subWeek())->get();
foreach($uploads as $date)
{
echo $date->created_at . '<br>';
}
}
}
EDIT 2
Here's another version I tried, but that didn't work out well.
class Admin
{
public static function uploadsGraph()
{
$date = \Carbon\Carbon::now();
$uploadsByDay = DB::table('uploads')
->select(DB::raw('
YEAR(created_at) year,
MONTH(created_at) month,
MONTHNAME(created_at) month_name
'))
->groupBy('year')
->groupBy('month')
->orderBy('year', 'desc')
->orderBy('month', 'desc')
->get();
dd($uploadsByDay);
}
}
I'm assuming that the number next to each day of the week represents the number of records made on that day, with the entire dataset you want to query ranging only over the last 7 days.
The idea here is to select the count of items that were created on the same day (ignoring completely the timestamp portion of the created_at column), so we can use DB::raw inside of a select() call to aggregate all of the entries that were created on a specific day and then restrict that dataset to only those created in the last week. Something like this ought to work:
$data = Upload::select([
// This aggregates the data and makes available a 'count' attribute
DB::raw('count(id) as `count`'),
// This throws away the timestamp portion of the date
DB::raw('DATE(created_at) as day')
// Group these records according to that day
])->groupBy('day')
// And restrict these results to only those created in the last week
->where('created_at', '>=', Carbon\Carbon::now()->subWeeks(1))
->get()
;
$output = [];
foreach($data as $entry) {
$output[$entry->day] = $entry->count;
}
print_r($output);
Also note that I assumed this to be a 'rolling' week, where if today happens to be a Thursday, then the first date in the dataset will be the previous Thursday. It will not start on the most recent Sunday, if that is what you need. If it is, you can change the -where() condition to something like this:
...
->where('created_at', '>=', Carbon\Carbon::parse('last sunday'))
...
DB::table("clicks")
->select("id" ,DB::raw("(COUNT(*)) as total_click"))
->orderBy('created_at')
->groupBy(DB::raw("MONTH(created_at)"))
->get();

Categories