Laravel/Eloquent and comparing dates - laravel

I want to return all of the rows in my database table that are a day or less old. I'm using Laravel 4. This is what I tried:
$date = date('Y-m-d H:i:s');
return MainContact::where(DATEDIFF('timestamp', $date), '<=', 1)->get();
This doesn't work. I read the documentation and it doesn't seem like you can pass Laravel MySQL functions. timestamp is a datetime field. How can I compare these dates in Laravel 4?

The answer that user1977808 gave you is not good because MySQL can't use an index on the timestamp column, since it has to compute an output of the DATE_SUB function for every row. Avoid such queries, they have to process the entire table every time!
How about something like this:
return MainContact::where('timestamp', '>=', time() - (24*60*60))->get();
I put the >= in there because you said "a day or less old", so they must have timestamp that is later than yesterday.

Alternatively,
You can use Carbon API that bundle with Laravel.
ModelName::where( 'timestamp', '>=', Carbon::now() )->get();
Reference: http://laravel.com/docs/5.1/eloquent-mutators

You could also use whereDate(), whereDay(), whereMonth() and whereYear(). In this case, whereDate() could be used as such, with Carbon's easy date functions:
return MainContact::whereDate('dateField', '<', Carbon::now()->subDay())->get();

return MainContact::where('timestamp', '>=', time() - (24*60*60))->get();

You can also do a raw query by using:
$results = DB::query( 'query' );
You only don't the the model object back in the results var

Related

Manual function inside query?

Is there any way to put a manual function inside a query in Laravel.
I've timestamp saved in string in DB. I want to convert timestamp from one timezone to another. All the timestamp is inserted in one time zone, and depending upon my user I fetch the timestamp and convert it into their timezone.
what I want to achieve is something like this..
$query = BlogCategory::select('merchant_id', userTime(added_at))
->where('site_id', $site_id)
->get();
userTime() function takes two parameter, the timestamp and the timezone and converts the timsestamp to time of the user.
I want to use userTime() function before fetching the data. I dont want to fetch the data first and then do foreach and so on.
I know I might be absolutely absurd but is there anything of this sort in Laravel?
Well you can achieved that using collection map
$query = BlogCategory::select('merchant_id', 'added_at')
->where('site_id', $site_id)
->get();
$dateAdded = $query->map(function ($data) {
// try this if error $data['merchant_id']
return array(
'merchant_id' => $data->merchant_id,
'added_at' => $this->userTime($data->added_at)
);
})
dd($dateAdded);
Read Collection documentation here: https://laravel.com/docs/5.8/collections
You should use the selectRaw statement and let your DB do this logic for you if you don't want to loop over the result set.
For example if your underlying database is MySQL you can use the CONVERT_TIMEZONE function and do something like this.
BlogCategory::selectRaw('merchant_id, CONVERT_TZ(added_at, "GMT", "MET") as added_at')
->where('site_id', $site_id)
->get();

Laravel Eloquent compare dates by specific format

I am having a little trouble comparing dates in Laravel, where the date is a specific format.
The field in the database has the date like this d-m-Y(20-04-2018) and I am trying to get a result where this date is greater than the date now using this.
$check= Usersubstitutions::where([
['user_id', '=', $request->user],
['date_to', '>=', date("d-m-Y")]
])->first();
And it never works. I var dumped to see what compares, using a foreach and it says that 20-05-2018 is NOT greater than 04-04-2018.
Convert your column to a date format, such as DATE, and then it will work as intended.
Since your field is a varchar try to cast it first to DATE then compare it with date('d-m-Y') like :
$check= Usersubstitutions::where('user_id', $request->user)
->where(DB::raw("DATE(date_to) >= '".date('d-m-Y')."'"))
->first();
NOTE : It will be better to convert the field type in your database to 'DATE'.
On Laravel 4+ you may use
->whereDate('date_to', '>=', date("d-m-Y")
For more examples, see first message of #3946 and this Laravel Daily article.
but you may also use the ->where() as its more convenient.
Try this:
$dayAfter = (new date()->modify('+1 day')->format('d-m-Y');
->where('date_to', '>=', $dayAfter)
Hope it helps. if not view this qn for further explanations
You seem to be storing a DATE in a varchar field. That's not a good idea. You need to either re-create the table and store date_to as a date using the standard SQL DATE format (and use the format Y-m-d when inserting) or cast the column to a date when selecting:
$check= Usersubstitutions::where([
['user_id', '=', $request->user],
[\DB::raw("STR_TO_DATE(date_to,'%d-%m-%Y')") ', '>=', date("Y-m-d")]
])->first();
Note this will make any indexes useless and will make the query run very very (very) slowly.
Note: STR_TO_TIME is MySQL only but there are equivalents in other DBMSs e.g. in SQL Server it seems to be CONVERT(DATE, date_to, 105)

Laravel compare timestamps in where statement

I have a block of code in which I am passing a Carbon date that looks like this:
2017-08-18 22:53:50.031922
And want to compare it to created_at time stamps of some records. However, it seems that the records are not being filtered out; is the comparison in the where statement valid?
$test = Auth::user()->tests()->with([
'participants.testRecords' => function ($query) use ($latestCapture) {
$query->select('id', 'score', 'test_id', 'participant_id', 'capture_timestamp', 'score', 'created_at');
$query->where('test_records.created_at', '>', $latestCapture);
}])->findOrFail($id)->toArray();
If $latestCapture is instancej Carbon, you should rather use here:
$latestCapture->toDateTimeString()
to make sure you pass valid date string.
There is also one more thing - you should make sure created_at is filled in PHP and not in MySQL (this is default in Laravel) - if it's not you can expect time shifts when you have different time zones in PHP and MySQL

How to detach only the last record in the pivot table using detach() in Laravel 4?

If I do this:
return $this->roles()->detach($role);
all roles are removed.
How to limit that to only the last one?
You can do it without timestamps:
$lastRole = $user->roles()
->orderBy( $user->roles()->getTable() .'id', 'desc')
->first();
$user->roles()->detach($lastRole);
or with timestamps:
$lastRole = $user->roles()->latest()->first();
$user->roles()->detach($lastRole);
you may try this, I did not test it:
return $this->roles()->orderBy('id', 'desc')->first()->detach($role);
You can also order by timestamps, if no primary id is present, like this:
return $this->roles()->orderBy('created_at', 'desc')->first()->detach($role);
for this to work, you also have to edit your model, from the docs:
If you want your pivot table to have automatically maintained
created_at and updated_at timestamps, use the withTimestamps method on
the relationship definition:
return $this->belongsToMany('Role')->withTimestamps();
Another thing would be not to use model at all, because looking at this issue #3585 it is not that easy. Taylor closed it without a comment, so I assume it not get implemented. The solution should be (assuming you have timestamps columns migrated in the table). Tested code:
$last = DB::table($user->roles()->getTable())
->orderBy('created_at', 'desc')
->first();
DB::table($user->roles()->getTable())
->where('created_at', '=', $last->created_at)
->delete();

Comparing dates in a query using Eloquent

How can I create a query like
WHERE DATE(created_date) = '2014-05-26'
in Laravel?
I got this
->where('created_date', Input::get('date'))
but it doesn't work because created_date is datetime
By using the DateTime class maybe :
->where('created_date', new DateTime(Input::get('date')))
It should work!
Try this
where('created_date', '>', $date->startOfDay()->toDateTimeString())
->where('created_date', '<', $date->endOfDay()->toDateTimeString())
->get();
and take a look at this:
Laravel eloquent get model on date
You have to convert you string representation of the date into a Carbon instance.
$date = Carbon\Carbon::parse(Input::get('date'));
$results = Model::where('created_date', $date);
Happy coding!
I think the best option, and most logical one, is the following:
$results = Model::whereDate('created_date', Input::get('date'));
Use of Carbon is optional here.

Resources