Different date accessors in same Model - php

I have this, and it works nicely to give me UK-formatted dates:
protected $dateFormat = 'd-m-Y';
protected $dates = ['purchased', 'warranty_expires', 'scrapped_on', 'location_date', 'user_date'];
However, I also have created and modified (not the standard Laravel ones, but my own) that are Timestamps, not dates. How can I automate the formatting of those two fields when they are retrieved, to something like 'd-m-Y H:i:s' ?

You can do this with Carbon library
public function getFormattedPurchasedAttribute($date)
{
return Carbon::createFromFormat('Y-m-d H:i:s', $date)->format('d-m-Y H:i:s');
}
You have to use carbon class. Write this line in the top where all namespace are used.
use Carbon;

I personally don't use $dateFormat attribute because it changes format for all dates fields. What I would do is creating custom accessors to get formatted fields for example:
public function getFormattedPurchasedAttribute($value) {
return $this->asDateTime($value)->format('d-m-Y H:i:s');
}
so you can now use $model-formatted_purchased to get purchased field formatted in way you want

Related

Change automatically the format of date fields (Laravel)

I'm looking for a DateTime Mutator that change the format of dates, I'm working with Oracle DB and the admitted Format is (DD/MM/YYYY) and the input type "date" stores dates in (YYYY,MM,DD) format.
I found the $date function and a trait by Torzer, but I have to indicate the fields that I want to convert the format.
is there some trait or function that detect all date fields and convert them automatically in a format (DD/MM/YYYY)? this without indicate the field.
nowadays I use protected $date in my model:
protected $dates = [ 'fecha_nac', 'fecha_nac1', 'fecha_nac2', ];
By default laravel uses date formate 'Y-m-d H:i:s' if you want to use a different format you can customize it in your model in the following way.
protected $dateFormat = 'your date formate';
in your case it will be.
protected $dateFormat = 'd-m-Y';
You can override the getDates method on HasAttributes trait.
/**
* Get the attributes that should be converted to dates.
*
* #return array
*/
public function getDates()
{
$defaults = [static::CREATED_AT, static::UPDATED_AT];
return $this->usesTimestamps()
? array_unique(array_merge($this->dates, $defaults))
: $this->dates;
}
On your model:
public function getDates()
{
$dates = parent::getDates();
// add your dynamic logic here
return $dates;
}
I would really go for explicitly defining which fields should be converted as these dynamic operations can be expensive if you are working with the model quite a lot.

Laravel mutate date before saving to database?

I have a date that's being selected in a datepicker in the following format
Y-m-d g:i A
So using AM/PM, it shows the following in my input field, which is correct
When I submit the form offcourse Laravel won't update the record because the format is unknown to my DATETIME field in mysql.
My 'date' field is added to the $dates array so it should be parsed by Laravel
I tried using a Mutator on my Model as following, without success
public function setDateAttribute($value)
{
$this->attributes['date'] = Carbon::createFromFormat('Y-m-d g:i A', $value)->format('Y-m-d H:i:s');
}
The original value is not being updated.
Any idea what I might be doing wrong?
Thank you
Take a look at Laravel's date mutators, this handles the accessing and mutating dates going into and out of the database for you much like it does with created_at and the other default dates.
Basically, you need to add the date field to the $dates array on your model like so:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'created_at', // Add if you're using timestamps on the model
'updated_at', // Add if you're using timestamps on the model
'deleted_at', // Add if you're using softDeletes on the model
'date'
];
}
This way when the model is persisted to the database it's done so as a DATETIME, whereas when it is being read from the database into your model it will be a Carbon instance
It seems that your carbon function is ok. But why it does not work, don't understand. But I have solution using PHP date function.
public function setDateAttribute($value)
{
$this->attributes['date'] = date("Y-m-d H:i:s", strtotime($value);
}
Laravel's date mutator expects a format like 'Y-m-d H:i:s', but you can use the $dateFormat attribute on your model to specify a different format. E.g.:
protected $dateFormat = 'Y-m-d g:i A';
Check out the Date Formats section in the docs under Date Mutators
Alternatively, you can parse the date using Carbon outside of the model, because attributes listed in the $dates will also accept Carbon instances:
$model->date = Carbon::createFromFormat('Y-m-d g:i A', '2016-11-29 02:00 PM');
This is the approach I typically use. To me this feels more like a front-end concern where you're trying to map a user-friendly format to one your models/DB expects, so I'll usually put this logic into a controller.

laravel 5 format datetime

I have an array that return the following date time:
$item['created_at'] => "2015-10-28 19:18:44"
And I need this outuput:
"2016-08-10T13:15:00.000+10:00"
Exist any function to convert this date?
Try this:
$dt = new \DateTime('2015-10-28 19:18:44', new \DateTimeZone('Europe/London'));
dd($dt->format('c')); // string '2015-10-28T19:18:44+00:00' (length=25)
Alternatively take a look at Carbon
You can use Laravel's accessors to get "reformatted" created_at.
public function getCreatedAtAttribute($value)
{
//Since Laravel uses Carbon you can do.
return $value->format('c');
}
This way anytime you do something like $model->created_at it will return modified created_at.
If you want to change datetime format for created_at in your database as well, you can use mutators.
More information you can find on the Laravel's docs page.

Validate Date and Time in the Laravel Model

I have a datepicker plugin to pop-up a calendar view to allow users to select a date + time, however the format which it produces is:
May 9, 2016 8:30 AM
When storing to the database, I need the format to be:
2016-09-05 08:30:00
In the controller of my application, I have:
public function save(Request $request)
{
Entry::create($request->all());
return redirect('entries');
}
Which saves the users form input, however it doesn't save the datetime due to the incorrect format. I have tried creating a new function to format the date before entering it into the database.
public function formatDate($data)
{
$returnDate = DateTime::createFromFormat('Y-d-m G:i:s', $data);
return $returnDate->format('Y-d-m G:i:s');
}
However when I call the function from the save function, it says undefined function. Am I doing something wrong or what would be the correct way to achieve this?
You have to set the correct format for DateTime::createFromFormat(). Create from format means, you have to tell a pattern to match any information in the given date. For your date, the pattern is:
DateTime::createFromFormat('F j, Y g:i A', $data);
Here is a demo: https://eval.in/567629
A list of all format options: http://php.net/manual/en/function.date.php
Both functions are inside the model?
If so, how are you trying to call the formatDate function?
You could use an anonymous function instead, try:
$formatted_date = function() use ($data) {
$returnDate = DateTime::createFromFormat('Y-d-m G:i:s', $data);
return $returnDate->format('Y-d-m G:i:s');
};
Inside your controller or model.
In Laravel, the created_at and updated_at are casted to Carbon objects
https://laravel.com/docs/5.2/eloquent-mutators#date-mutators
With your date, you could do the same thing
class User extends Model
{
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'your_date'];
}
then, when saving the date, it will be cast to the correct format.
Give that a try and let us know how you get on!
For example;
$data = "May 9, 2016 8:30 AM";
return date('Y-d-m H:i:s',strtotime($data));

How do I change the date format Laravel outputs to JSON?

I've built an application in Laravel and eloquent returns dates in this format: 2015-04-17 00:00:00. I'm sending one particular query to JSON so I can make a graph with D3, and I think I would like the dates in ISO8601 ('1995-12-17T03:24:00') or some other format that plays nice with the javascript Date() constructor.
Is there a way to change the date format being output to JSON on the Laravel end? I'm not sure using a mutator is the best approach because it would affect the date in other parts of my application.
Or would it be better to leave the JSON output as is, and use some javascript string methods to manipulate the date format before passing it to the Date() constructor? Which approach is more efficient?
Here is my model:
class Issue extends Model {
protected $fillable = [
'client_id',
'do',
'issue_advocate',
'service_number',
'issue_location',
'issue_description',
'level_of_service',
'outcome',
'referral_id',
'file_stale_date',
'date_closed',
'issue_note',
'staff_hours'
];
protected $dates = [
'do',
'date_closed',
'file_stale_date'
];
public function setDoAttribute($value)
{
$this->attributes['do'] = Carbon::createFromFormat('F j, Y', $value)->toDateString();
}
}
Here is my query:
$issues = Issue::with('issuetypes')
->select(['do','level_of_service','outcome','id'])
->whereBetween('do',[$lastyear,$now])
->get()->toJson();
And the JSON I get back:
[{"do":"2014-12-23 00:00:00","level_of_service":1,"outcome":1,"id":18995,"issuetypes":[{"id":9,"issuetype":"Non Liberty","pivot":{"issue_id":18995,"issuetype_id":9}}]}]
I know it's an old question, but there is still no good answer to that.
Changing protected $dateFormat will affect database, instead method serializeDate() must be overriden
class MyModel extends Eloquent {
protected function serializeDate(\DateTimeInterface $date) {
return $date->getTimestamp();
}
}
Or myself I chose to create trait
trait UnixTimestampSerializable
{
protected function serializeDate(\DateTimeInterface $date)
{
return $date->getTimestamp();
}
}
and then add
class SomeClassWithDates extends Model {
use UnixTimestampSerializable;
...
}
Expanding on umbrel's answer a bit I've created a trait that turns the DateTimeInstance into a Carbon instance so that I can easily make use of it's common formats.
In my particular case I wanted to serialize all dates according to ISO-8601.
The trait is as follows...
use DateTimeInterface;
use Carbon\Carbon;
trait Iso8601Serialization
{
/**
* Prepare a date for array / JSON serialization.
*
* #param \DateTimeInterface $date
* #return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return Carbon::instance($date)->toIso8601String();
}
}
and from here I can simply use it on the relevant models...
class ApiObject extends Model
{
use Iso8601Serialization;
}
Obviously you could name the trait more appropriately if you're using a different format but the point is that you can use any of Carbon's common formats simply by replacing toIso8601String() with the format you need.
I strongly suggest you use the Carbon class to handle all your dates and datetimes variables, it already comes with Laravel 5 so you can start using whenever you want.
Check it out on Carbon Repo to see what you can do with it.
As an example, you can format dates from your model like this
Carbon::parse($model->created_at)->format('d-m-Y')
As for a good approach, I would suggest to use the Repository Pattern along with Presenters and Transformers. By using it you can define how you want your json to be displayed/mounted and opt to skip the presenter whenever you want in order to still get you Eloquent model returned when you make your queries.
use this function in any Model
protected function serializeDate(DateTimeInterface $date){
return $date->format('Y-m-d h:i:s');
}
Result
You can easily change the format that used to convert date/time to string when your models are serialized as JSON by setting $dateFormat property of your model to the format you need, e.g.:
class MyModel extends Eloquent {
protected $dateFormat = 'Y-m-d';
}
You can find docs on different placeholders you can use in the format string here: http://php.net/manual/en/datetime.createfromformat.php
If you use usuals techniques as
protected $dateFormat = 'Y-m-d';
or
protected function serializeDate(DateTimeInterface $date) { ... }
or
protected $casts = [ "myDate" => "date:Y-m-d" ];
It'll only works when laravel will serialize itself objects. And you will anyway to put those code inside all models, for all properties.
So my solution, you have to (too) put this code in all models for all date properties by at last, it works in ALL cases :
public function getMyDateAttribute()
{
return substr($this->attributes['my_date'], 0, 10);
}

Categories