Laravel / Eloquent - When date is in the past - php

I am working on an application which uses Laravel and Eloquent that determines whether something (a job) has not been completed on time. This is stored as a DATE within the table. E.g. 2016-07-18
I am trying to get all the records where todays date is greater than the "completed_date" stored inside the table.
Here is what I have tried:
$id = \Auth::user()->id;
$now = \Carbon\Carbon::today();
$jobs = Job::whereHas('manager', function ($user) use ($id) {
$user->where('users.id', '=', $id);
})->where('complete_date', '>', $now)->get();
The issue is that it's still retrieving records that are in the future. For example, the record it returns, I checked the table and the "complete_date" is 2016-08-31
Any ideas please?

Your $now variable is a Carbon object, not a date.
You have to convert the object to a date:
$now = \Carbon\Carbon::now()->format('Y-m-d');
Then you have to use this variable in your model query.

Related

How do I make the unique check on month of a year in Laravel

Here is a table named installments which has date_of_receipt and user_id columns. I need to check if a date date_of_receipt = 27-01-2019 has present according to a user so I have to validate this entity already exists here for any January 2019 day. How can I do that in Laravel5.7 with MySQL?
Because you are storing it as a string in a particular format, you could achieve this with something like this:
$start = \Carbon\Carbon::parse($request->date_of_receipt)->startOfMonth()->format('d-m-Y');
$end = \Carbon\Carbon::parse($request->date_of_receipt)->endOfMonth()->endOfDay()->format('d-m-Y');
return DB::table('installments')
->where('user_id', $user_id)
->whereBetween('date_of_receipt', [$start, $end])
->exists();

How to get last 12 months user login data by per month in laravel

I am trying to get user login activity per month and then to show it in statistic in a bar chat. But the problem i am facing is that its not giving me any data. I will share my code first it will easier to explain my problem
My LoginActivity Model
class LogActivity extends Model
{
protected $table = 'laravel_logger_activity';
public function logActivity(){
$videoPerMonth = array();
for ($i=1; $i<=12; $i++){
$age= 12 - $i;
$userPerMonth[$i] = count(LogActivity::whereNotIn('userId', [1])->whereMonth('created_at', '=', date('n') -$age)->get());
}
}
}
In this i do get user's activity per month but this is not accurate because being the first month if u subtract 12 value goes to negative. And i dont get actual reults.
So, after reading few articles i changed my code to this
$userPerMonth =count( LogActivity::whereNotIn('userId', [1])->whereMonth('created_at', '>=', Carbon::now()->subMonth(12))->get());
return json_encode($userPerMonth);
But this returns empty.What shall i do ?
I want to get data by month vs activity
For example nov 2017 : 300 , dec 2017:800,jan 01 2018:100
Something like that so i can put in bar chat
Can anyone please help me with this
Thanks
I would be tempted to tackle this in a different way, instead of trying to get the user's login activity per month in a loop. I would get the user's login activity for a date range such as a year. This would result in one SQL query being run rather than 12 per user. Once you have the data you can loop through the results and sort them into an array or collection.
Or you could do it as the equivalent of this SQL statement.
SELECT COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id
FROM login_tokens
WHERE created_at >= '2017-01-01 00:00:01' AND created_at <= '2017-12-31 23:59:59'
GROUP BY user_id, login_month
I think to do this in eloquent you would need to do the following;
$logActivity = LogActivity::where(‘created_at’, ‘>=’, ‘2017-01-01 00:00:01’)
->where(‘created’, ‘<=’, ’23:59:59’)
->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id’))
->groupBy(‘user_id’)
->groupBy(‘login_month’)
->get();
Downside to this approach is you're having to put in knowledge of the SQL language, which could differ from MySql, to SQLite, MSSQL etc.
A useful tip if you remove the get() and replace it with toSql() you can echo out the query.
echo LogActivity::where(‘created_at’, ‘>=’, ‘2017-01-01 00:00:01’)
->where(‘created’, ‘<=’, ’23:59:59’)
->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%m') as login_month, user_id’))
->groupBy(‘user_id’)
->groupBy(‘login_month’)
->toSql();
dd();
Hope that helps a bit.
I've knocked together a simple class that is more or less what I think you're after. Please note that the use statements are probably not quite right and I've not run this code, so use it as an example. Basically what I've done here is get the current date and work out the previous year from now.
That is then used to select the data from the database within getActivity method. An empty array is created $dateRange for storing the results in with the keys being the year and the month i.e. 2018-02, 2018-01, 2017-12, 2017-11 and so on.
Next I'm doing a simple check to see if we actually have any results from the database because if there are no results then the logins would be 0 for each month.
Then get a date range, okay I've swapped back to standard PHP date interval here as I don't know the Carbon syntax of the top of my head, but as Carbon extends PHP's DateTime it probably should work. However, it may need some tweaking here as well. So get the date range between the two dates by a monthly interval.
Then loop through this date range, use the $hasLoginActivity variable we defined earlier and if that's false add the date range formatted to year-month as the key and the value to zero.
If we have results then add the date range with the same formatting and get the data from the results. As we have returned a collection from Laravel's ORM we should be able to where on it again, see Collections docs. Store this to a variable and check to see if we have results before trying to access the property, else set to zero. You might be able to skip this and access it like $loginActivity->where('login_year_month', $date->format('Y-m'))->login_num; but I can't remember of the top of my head if this causes an error trying to access property on a null value.
I hope this helps.
<?php
use Carbon;
use DateInterval;
use DatePeriod;
use LogActivity as LogActivityModel;
class LogActivity
{
public function annualActivity(): array
{
// Get the current date/time and get a year from now.
$now = new Carbon();
$aYearAgo = $now->clone()->subYears(1);
// Get any login activity from the last year to now.
$loginActivity = $this->getActivity($aYearAgo, $now);
$dateRange = [];
$hasLoginActvity = $loginActivity->count();
// Get a date range from a year ago to now and loop through them.
foreach ($this->getDateRange($aYearAgo, $now) as $date) {
// If we there were no results, then just create the array with a result set of zero.
if (! $hasLoginActvity) {
$dateRange[$date->format('Y-m')] = 0;
continue;
}
$monthActivity = $loginActivity->where('login_year_month', $date->format('Y-m'));
$loginCount = $monthActivity ? $monthActivity->login-num : 0;
// Add to the array the date YYYY-MM as the key i.e. 2018-02 and search the collection for the same date.
$dateRange[$date->format('Y-m')] = $loginCount;
}
// Return the array date with the year and month as the key and a integer as the value.
return $dateRange;
}
private function getActivity(Carbon $aYearAgo, Carbon $now)
{
return LogActivityModel::where(‘created_at’, ‘>=’, $aYearAgo->format('Y-m-d H:i:s'))
->where(‘created_at’, ‘<=’, $now->format('Y-m-d H:i:s'))
->select(\DB:raw(‘COUNT(*) as login_num, DATE_FORMAT(created, '%Y-%m') as login_year_month, user_id’))
->groupBy(‘user_id’)
->groupBy(‘login_month’)
->all();
}
private function getDateRange($from, $to)
{
// Get a the date range between the two dates with an interval of a month.
return new DatePeriod($from, new DateInterval('P1M') ,$to);
}
}

Eloquent - Get records by day

I have a list of database records that represent some events. Each has a start_time column that contains dates in this format: 2017-10-28 22:00:00. I would like to be able to get all the records whose column start_time is a Friday using Laravel. Something like this:
$fridayEvents = $q->whereDate('start_time', '=', isFriday());
But I am having a hard time creating isFriday() with Carbon.
MySQL (and other SQLs) implement the WEEKDAY() function that extracts the weekday from a date:
WEEKDAY(date)
Returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 =
Sunday).
mysql> SELECT WEEKDAY('2008-02-03 22:23:00');
-> 6
mysql> SELECT WEEKDAY('2007-11-06');
-> 1
So you can do a query like this:
$q->whereRaw('WEEKDAY(your_table_name.start_date) = 4')
This way is more efficient then filtering results directly on PHP using Carbon:
You will process data using native database functions that are faster then Carbon over PHP.
Only the relevant data will travel from Database to PHP, reducing query time and memory usage
To get the top performance, you'll need to create a column to store the weekday, so your database will be able to use indexes to avoid full-table scan, giving you the best performance.
whereDate() will only check the dates, so you can't check day with whereDate()
For achieving your goal, you need to perform couple of operations, I am using psuedocode as I don't know how you are querying.
$records = Event::get();
$filteredArray = array();
foreach($records as $record){
if(Carbon::parse($record->start_time)->dayOfWeek == Carbon::FRIDAY || Carbon::parse($record->start_time)->dayOfWeek == Carbon::SATURDAY){
$fillteredArray[]= $record;
}
}
I hope it helps :)
Assuming the model's $casts property is properly casting the column to a date, one can easily apply the filter method using Carbon's dayOfWeek property.
/** #var \Illuminate\Support\Collection $events */
$fridays = $events->filter(
fn ($v, $k) => $v->start_time->dayOfWeek === Carbon::FRIDAY
);
Now $fridays will only contain those events that started on a Friday. Note the database method detailed in the other answer remains more efficient in cases where you have the option to use it, but this may be helpful when extracting a subset from an existing collection.
use Carbon\Carbon;
// this will return an array of events
$fridayEvents = $q->start_time;
// assign empty array variable
$dates = [];
//loop on the events
foreach($fridayEvents as $event){
// Use carbon to parse make sure it is a date not a string type then reformat it by using format() and the small 'l' inside the format returns the exact name for the day of that date
// so if it is friday go and push into the array the entire event
if(Carbon::parse($event)->format('l') == 'Friday'){
array_push($dates, $event);
}
}
// die and dump the data after pushing into the $dates the events
dd($dates);

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.

How to compare date with mongodb iso date in laravel mongodb eloquent query?

I want to get record from data where date is greater than given date. But I am getting problem in comparing date with mongodb iso datetime.
Currently I am getting date in Y-m-d format which I want to compare in query and date in mongodb is in 2015-10-08T08:01:46.000Z format.
Laravel's Eloquent supports Carbon/DateTime objects instead of MongoDate objects which will be converted internally to MongoDate objects when saved to the database. You could use this date handling package in laravel called Carbon with your queries.
For example, if you want to query for records from Users data where a mongodb datetime field created_at is greater that a given date, say records from today, use Carbon's startOfDay() property:
$dt = Carbon::now()->startOfDay();
$users = User::where('created_at', '>', $dt)->get();
Similarly, to do a data range query i.e. query for records between a specific month, say October of 2015, use the whereBetween method:
$users = User::whereBetween(
'created_at', array(
Carbon::createFromDate(2015, 10, 1),
Carbon::createFromDate(2015, 10, 31)
)
)->get();
Another approach would be to use Eloquent which allows you to work with Carbon/DateTime objects instead of MongoDate objects. Example inspired from the docs:
<?php
use Jenssegers\Mongodb\Model as Eloquent;
class User extends Eloquent {
use SoftDeletingTrait;
/**
* Collection for Model
*
* #var String
*/
protected $collection = "users";
/**
* Connection for model
*
* #var type
*/
protected $connection = 'mongodb';
protected $dates = array('created_at');
}
Which allows you to execute queries like:
$users = User::where('created_at', '>', new DateTime('-1 day'))->get();
Or natively using MongoDate objects, you could try
$start = new MongoDate(strtotime("2015-10-01 00:00:00"));
$stop = new MongoDate(strtotime("2015-10-31 00:00:00"));
$users = DB::collection('users')->whereBetween('created_at', array($start, $stop))->get();
The simplest way for you to compare a date is to use Carbon.
For example, if you want to get from Y-m-d,
you can just use this:
$dt = Carbon::createFromDate(2017,11,7);
where 2017 = year, 11 = month, and 7 = day. Replace it according to your needed date.
If you want to get data before current time, you can use
$dt = Carbon::now()
And if you want to get data from the 1st day of current month onwards, you'll just do this:
$dt = Carbon::now()->startOfMonth();
Below is a an example of what I used in my code:
$device_data = DB::connection('mongodb')
->table('MyRecipe')
->where('data_date', '>', $dt)
->select('*')
->get();
I'm using https://github.com/jenssegers/laravel-mongodb to access my Mongo database.

Categories