Laravel blade does not respect date cast formatting - php

I have a birth date field in users table
$table->date('dob');
User model has Casts
protected $casts = [
'dob' => 'date:d-m-Y'
];
In Blade,
{{$user->dob}}
I was expecting 26-11-2019
but found it shows 2019-11-26 00:00:00
Why I need to format the date again in blade when display?
What did I miss?
Or what I was expecting, is not the purpose of formatting?

protected $casts = [...] tells Laravel to treat the properties as Carbon instances, but you still need to format them:
{{ $user->dob->format('d-m-Y') }}
As far as I'm aware, there isn't a way to output a default format, unless you use an accessor:
In your User.php model:
public function getDobFormattedAttribute(){
return $this->dob->format('y-m-D');
}
Then in your view:
{{ $user->dob_formatted }}

Date casting uses only for arrays or JSON, as explained here:
https://laravel.com/docs/6.x/eloquent-mutators#date-casting
You can try to do it via mutator:
https://laravel.com/docs/6.x/eloquent-mutators#date-mutators
protected $dates = [
'dob', // it will be 'Y-m-d H:i:s'
];
protected $dateFormat = 'd-m-Y'; // but you can redefine it

that will only work when you use a ->toArray() or ->toJson() on the object or collection in question, from the doc here https://laravel.com/docs/6.x/eloquent-mutators#date-casting
A way around that of you weren't using any of the above function call is to create an accessor or getter method in the model.
use Carbon\Carbon; // import the Carbon lib.
protected $dates = ['dob'];
public function getDobAttribute($value)
{
return Carbon::createFromFormat('d-m-Y', $value);
}

Related

how do you parse this date in PHP

I want to ask if how do you parse this date to look like : "12/24/1990" using Carbon in laravel or built in php date methods
$user->profile->birthdate
Just do this
use Carbon\Carbon;
Carbon::parse($user->profile->birthdate)->format('m/d/Y')
You may use date mutators like this in your Profile model (or date casting as #Jesper said):
class Profile extends Model
{
protected $dates = [
'birthdate', // date fields that should be Carbon instance
];
}
So, whenever you retrieve the model, Laravel will automatically cast the birthdate property to Carbon instance and you can use the format method to format it, for example:
$user->profile->birthdate->format('m/d/y');
Both solutions works for both Laravel 5.* and 6.*
First Solution
You can cast your birthdate variable to always be in the format you want, by putting the following in your Profile model.
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'birthdate' => 'datetime:m/d/Y',
];
Reference:
https://laravel.com/docs/6.x/eloquent-mutators#date-casting
Second solution:
You can also cast the birthdate to always be a Carbon object in your Profile model, which you can then later format as you want, using the following code:
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'birthdate',
];
And then you can always do the following to format it in different ways:
$user->profile->birthdate->format('m/d/Y')
Reference: https://laravel.com/docs/6.x/eloquent-mutators#date-mutators
Using laravel Carbon, you can parse date like below
$carbonToday = Carbon::now();
$date = $carbonToday->format('m/d/Y');
Using PHP method
$carbonToday = Carbon::now();
$date = date('m/d/Y',strtotime($carbonToday));
Hope this will help you.
using Laravel carbon method
$date = "12-24-1990";
$carbon_date = Carbon\Carbon::createFromFormat('m/d/Y', $date);
using PHP method
$newdate = date('m/d/Y',strtotime($date));

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.

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

How to customize date mutators in Laravel?

I've created a few datetime fields in my database, and as is described in Laravel documentation, I can "customize which fields are automatically mutated". However there's no example showing how it can be done, nor is there any search result. What should I do to make certain fields auto mutate?
For example, I created a table called "people" in migration, one of the fields is defined as this:
class CreatePeopleTable extends Migration {
public function up(){
Schema::create("bookings",function($table){
...
$table->dateTime("birthday");
...
}
}
}
And I defined a model for "people" in models:
class People extends Eloquent{
//nothing here
}
If I refer to the birthday of a People instance, it'll be string, instead of DateTime
$one=People::find(1);
var_dump($one->birthday);
//String
The date mutator should be able to convert it directly to Carbon object, but the documentation doesn't say much about how it should be implemented.
In your People model just add this array:
protected $dates = array('birthday');
Laravel's Model.php internaly merges your fields with the default ones like this:
/**
* Get the attributes that should be converted to dates.
*
* #return array
*/
public function getDates()
{
$defaults = array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT);
return array_merge($this->dates, $defaults);
}
According to this doc, you can use model member function getDates() to customize which fileds are automatically mutated, so the following example will return Carbon instance instead of String:
$one = People::find(1);
var_dump($one->created_at);//created_at is a field mutated by default
//Carbon, which is a subclass of Datetime
But it doesn't say clearly how to add your own fields. I found out that the getDates() method returns an array of strings:
$one = People::find(1);
echo $one->getDates();
//["created_at","modified_at"]
So what you can do is appending field names to the return value of this method:
class People extends Eloquent{
public function getDates(){
$res=parent::getDates();
array_push($res,"birthday");
return $res;
}
}
Now birthday field will be returned as a Carbon instance whenever you call it:
$one = People::find(1);
var_dump($one->birthday);
//Carbon
What do you mean by: automatically mutated?
If you mean mutated after being retrieved from DB use Accessors and Mutators (Laravel docs).
Add this to your model:
public function getDateAttribute( $date )
{
// modify $date as you want, example
// $date = new \Carbon\Carbon($date);
// $date->addDay()
// return (string)$date
}
As Sasa Tokic says, add protected $dates = array('birthday'); to your People model like so:
class People extends Eloquent{
protected $dates = array('birthday');
}
You can then use Carbon to do clever things to this value, like so:
$people->birthday->format('jS F Y')
PHP's date() function docs (http://uk3.php.net/manual/en/function.date.php) and Carbon's docs (https://github.com/briannesbitt/Carbon) will help here:

Categories