Laravel and MySQL get data by week - php

I have this function that gets the data from MySQL by month using carbon
$calls = \DB::table('calls')
->where('owned_by_id', $report->id)
->where(\DB::raw('month(created_at)'), Carbon::today()->month)
->get();
$report->callsCount = $calls->count();
It works fine what i want to do is to get the data per week
I tried modifying the code like this:
->where(\DB::raw('week(created_at)'), Carbon::today()->week)
but i get an error in Laravel
Unknown getter 'week'

Look you need to filter date by week which mean date range try this
$calls = \DB::table('calls')
->where('owned_by_id', $report->id)
->whereBetween('created_at', [Carbon::now()->subWeek()->format("Y-m-d H:i:s"), Carbon::now()])
->get();
$report->callsCount = $calls->count();
This mean to get all data from last 7 days to now based on carbon docs https://carbon.nesbot.com/docs/ and laravel docs https://laravel.com/docs/5.8/queries#where-clauses

Use whereBetween with two carbon date instances.
->whereBetween('created_at', [
Carbon\Carbon::parse('last monday')->startOfDay(),
Carbon\Carbon::parse('next friday')->endOfDay(),
])

Like #Abrar says, if you need to count total calls of the current month u can use whereBetween:
$calls = \DB::table('calls')
->where('owned_by_id', $report->id)
->whereBetween('created_at', [
now()->locale('en')->startOfWeek(),
now()->locale('en')->endOfWeek(),
])
->get();
$report->callsCount = $calls->count();
But u want to count the total numerb of calls per each week u need to use groupBy.
Good luck!

Related

Laravel: get users created more than three months ago

in my laravel app I want to get all records of users where "created_at" timestamp is older than three months from current date, is it possible to achieve this with Eloquent query builder?
First, you can use Carbon to get the date of 3 months ago.
$date = Carbon::now()->subMonths(3)->format('Y-m-d');
And then we need all the records before that that. So, query should be-
$users = User::where('created_at', '<=', $date)->get();
belowe code can help you to solve problem
$three_month = Carbon::now()->startOfMonth()->subMonth(3);
$data = DB::table('orders')
->where('placed_at','>',$three_month)
->get();
$dateS = Carbon::now()->startOfMonth()->subMonth(3);
$dateE = Carbon::now()->startOfMonth();
$usersArr = $users
->whereBetween('created_at',[$dateS,$dateE])
->get();
startOfMonth() begins with 1st date of the month
To find users older than three months
$users = User::where('created_at','<', today()->subMonths(3))->get();
The easiest way to make it done by using carbon. Use the below code-
User::where( 'created_at', '<=', Carbon::now()->subMonths(3))->get();
Eloquent can compare datetimes. You can use Carbon to get the date you want to compare to and use it in your eloquent query.
$threeMonthsAgo = now()->subMonth(3);
$users = User::where('created_at', '<' , $threeMonthsAgo)->get();

Laravel Carbon, querying database where a field date is 2 weeks less than itself

I have a Election model, where I'm trying to write a query that will show me specific results.
The idea is pretty simple:
A Election starting_date, for example is 15/10/2018.
I need my query to show all elections that will start in next 2 weeks.
I mean, for that specific case, today is 01/10/2018, so I need all elections that will start in period 01/10/2018 - 15/10/2018.
So, I tried to write something like:
public function notificationBeforeCollection() {
return $this->activeElections()
->where('start_collection', '>=', Carbon::now()
->subDays(14)->format('Y-m-d'))
->where('start_collection', '<', Carbon::now()
->format('Y-m-d'));
}
But it doesn't work, and it looks like it can't work by comparing the starting_date with today. It looks like I need to write something like:
where('starting_date', '>=', 'starting_date'->subDays(14);
If I'm right, is there a way how to use Carbon against a field in query builder?
Your actual query is looking for all elections that started 14 days ago.
You need to do something like:
return $this->activeElections()->where('start_collection', '>', Carbon::today())
->where('start_collection', '<=' Carbon::today()->addDays(14));
To get 'Elections' of two weeks from tomorrow
// using 'Carbon'
$start_date = Carbon::now()->addDay()->format('Y-m-d');
$end_date = Carbon::now()->addDays(14)->format('Y-m-d');
public function notificationBeforeCollection() {
return $this->activeElections()->whereBetween(
'start_collection', [$start_date, $end_date]
);
}

How to get only the current date and the previous dates in laravel?

I am trying to get only the current dates and the previous dates.Here is how i tried
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')
->get()->where('call_back_date', '<=', Carbon::today()->toDateString());
This show only the previous dates, i want to get both.If i remove "<", it shows only the current date.Help me out please.
Use tomorrow and < condition
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')
->get()->where('call_back_date', '<', Carbon::tomorrow()->toDateString());
use below eloquent query
$jobseekers = Calllog::whereDate('call_back_date','<=',Carbon::today)->get()
$jobseekers = Calllog::orderBy('calllogs.created_at','DESC')->where('call_back_date', '<=', Carbon::now())->get();
Using now() instead of today(). Unlike today(), now() returns complete datetime at the moment.
Also notice that i moved where condition before get() to prevent fetching extra data from database.

Laravel Eloquent whereDate() with UnixTimestamps

the entries in my database have a custom timestamp field (e.g. 1488446089).
How do I use whereDate() or whereDay() with unix timstamps?
This of course just works for Date Fields.
$posts = Post::whereDay('uploaded_time', '=', '2017-05-10')->get();
To run it correctly use whereDate instead of whereDay
$posts = Post::whereDate('uploaded_time', '2017-05-10')->get();
To get all specific day means (date of month like 1-30)
$posts = Post::whereDay('uploaded_time', '10')->get();//provide date of month
get more detail : https://laravel.com/docs/master/queries#where-clauses
One way to do this is fetching all Posts, and then filtering the results in PHP:
$myDate = '2017-05-10';
$posts = Post::all()->filter(function (Post $post) use ($myDate) {
$uploadedAt = Carbon::createFromTimestamp($post->uploaded_time)->format('Y-m-d');
return $uploadedAt === $myDate;
});
Why? Because if I'm right you are trying to fetch all posts that were uploaded on a certain date. This means that there is a range of timestamps valid. (60 * 60 * 24). With Carbon (comes with Laravel) you can easily convert your timestamps to Y-m-d formatted strings. Those you then compare to the date string of your choice.
Edit
I have no way to test this at the moment, but it should be possible to do this with a query builder after all:
$myDate = Carbon::createFromFormat('Y-m-d', '2017-05-10');
$startOfDayTimestamp = $myDate->startOfDay()->timestamp;
$endOfDayTimestamp = $myDate->endOfDay()->timestamp;
$posts = Post::whereBetween('uploaded_time', [
$startOfDayTimestamp,
$endOfDayTimestamp
])->get();
Here we create 2 timestamps, one for the very start of the date you wish to filter by, and one for the very end. After that, we can use the builder's whereBetween() method and pass the 2 timestamps.
I found this solution here, and simplified a little bit by replacing the setTime() calls with startOfDay and endOfDay methods.

Laravel Eloquent get results grouped by days

I currently have a table of page_views that records one row for each time a visitor accesses a page, recording the user's ip/id and the id of the page itself. I should add that the created_at column is of type: timestamp, so it includes the hours/minutes/seconds. When I try groupBy queries, it does not group same days together because of the seconds difference.
created_at page_id user_id
========== ======= =======
10-11-2013 3 1
10-12 2013 5 5
10-13 2013 5 2
10-13 2013 3 4
... ... ...
I'd like to get results based on views/day, so I can get something like:
date views
==== =====
10-11-2013 15
10-12 2013 45
... ...
I'm thinking I'll need to dig into DB::raw() queries to achieve this, but any insight would help greatly, thanks
Edit: Added clarification of created_at format.
I believe I have found a solution to this, the key is the DATE() function in mysql, which converts a DateTime into just Date:
DB::table('page_views')
->select(DB::raw('DATE(created_at) as date'), DB::raw('count(*) as views'))
->groupBy('date')
->get();
However, this is not really an Laravel Eloquent solution, since this is a raw query.The following is what I came up with in Eloquent-ish syntax. The first where clause uses carbon dates to compare.
$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
->groupBy('date')
->orderBy('date', 'DESC')
->get(array(
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as "views"')
));
You can use Carbon (integrated in Laravel)
// Carbon
use Carbon\Carbon;
$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('Y'); // grouping by years
//return Carbon::parse($date->created_at)->format('m'); // grouping by months
});
Here is how I do it. A short example, but made my query much more manageable
$visitorTraffic = PageView::where('created_at', '>=', \Carbon\Carbon::now->subMonth())
->groupBy(DB::raw('Date(created_at)'))
->orderBy('created_at', 'DESC')->get();
Like most database problems, they should be solved by using the database.
Storing the data you want to group by and using indexes you can achieve an efficient and clear method to solve this problem.
Create the migration
$table->tinyInteger('activity_year')->unsigned()->index();
$table->smallInteger('activity_day_of_year')->unsigned()->index();
Update the Model
<?php
namespace App\Models;
use DB;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class PageView extends Model
{
public function scopePerDay($query){
$query->groupBy('activity_year');
$query->groupBy('activity_day_of_year');
return $query;
}
public function setUpdatedAt($value)
{
$date = Carbon::now();
$this->activity_year = (int)$date->format('y');
$this->activity_day_of_year = $date->dayOfYear;
return parent::setUpdatedAt($value);
}
Usage
$viewsPerDay = PageView::perDay()->get();
You can filter the results based on formatted date using mysql (See here for Mysql/Mariadb help) and use something like this in laravel-5.4:
Model::selectRaw("COUNT(*) views, DATE_FORMAT(created_at, '%Y %m %e') date")
->groupBy('date')
->get();
I had same problem, I'm currently using Laravel 5.3.
I use DATE_FORMAT()
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
Hopefully this will help you.
PageView::select('id','title', DB::raw('DATE(created_at) as date'))
->get()
->groupBy('date');
To group data according to DATE instead of DATETIME, you can use CAST function.
$visitorTraffic = PageView::select('id', 'title', 'created_at')
->get()
->groupBy(DB::raw('CAST(created_at AS DATE)'));
Warning: untested code.
$dailyData = DB::table('page_views')
->select('created_at', DB::raw('count(*) as views'))
->groupBy('created_at')
->get();
I know this is an OLD Question and there are multiple answers. How ever according to the docs and my experience on laravel below is the good "Eloquent way" of handling things
In your model, add a mutator/Getter like this
public function getCreatedAtTimeAttribute()
{
return $this->created_at->toDateString();
}
Another way is to cast the columns
in your model, populate the $cast array
$casts = [
'created_at' => 'string'
]
The catch here is that you won't be able to use the Carbon on this model again since Eloquent will always cast the column into string
Hope it helps :)
Using Laravel 4.2 without Carbon
Here's how I grab the recent ten days and count each row with same day created_at timestamp.
$q = Spins::orderBy('created_at', 'desc')
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d')"))
->take(10)
->get(array(
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as "views"')
));
foreach ($q as $day) {
echo $day->date. " Views: " . $day->views.'<br>';
}
Hope this helps
You could also solve this problem in following way:
$totalView = View::select(DB::raw('Date(read_at) as date'), DB::raw('count(*) as Views'))
->groupBy(DB::raw('Date(read_at)'))
->orderBy(DB::raw('Date(read_at)'))
->get();
this way work properly and I used it in many projects!
for example I get data of views the last 30 days:
$viewsData = DB::table('page_views')
->where('page_id', $page->id)
->whereDate('created_at', '>=', now()->subDays(30))
->select(DB::raw('DATE(created_at) as data'), DB::raw('count(*) as views'))
->groupBy('date')
->get();
If you want to get the number of views based on different IPs, you can use the DISTINCT like below :
$viewsData = DB::table('page_views')
->where('page_id', $page->id)
->whereDate('created_at', '>=', now()->subDays(30))
->select(DB::raw('DATE(created_at) as data'), DB::raw('count(DISTINCT user_ip) as visitors'))
->groupBy('date')
->get();
You can easily customize it by manipulating the columns name
you can use the following code to group them by the date, since you have to parse both in the selection query and in the groupBy method:
$counts = DB::table('page_views')->select(DB::raw('DATE(created_at) as created_at'), DB::raw('COUNT(*) as views'))->
groupBy(DB::raw('DATE(created_at)'))->
get();
in mysql you can add MONTH keyword having the timestamp as a parameter
in laravel you can do it like this
Payement::groupBy(DB::raw('MONTH(created_at)'))->get();
I built a laravel package for making statistics : https://github.com/Ifnot/statistics
It is based on eloquent, carbon and indicators so it is really easy to use. It may be usefull for extracting date grouped indicators.
$statistics = Statistics::of(MyModel::query());
$statistics->date('validated_at');
$statistics->interval(Interval::$DAILY, Carbon::createFromFormat('Y-m-d', '2016-01-01'), Carbon::now())
$statistics->indicator('total', function($row) {
return $row->counter;
});
$data = $statistics->make();
echo $data['2016-01-01']->total;
```
Get pages views (or whatever), group my year-month-day and count for each date:
PageView::get()
->groupBy(fn($pv) => $pv->created_at->format('Y-m-d'))
->map(fn($date) => count($date));

Categories