What's a good way of storing a date in a Eloquent Model? I'm using PHP with Laravel framework.
class MyModel extends Eloquent {
// I want a date field here... should it be:
public $endTime = ?;
}
Should I use a integer timestamp which gets saved as an int? What's the behaviour if I use a Date object in a atributte and save that object?
If you are using migration then use $table->timestamp('endTime'), this will create a timestamp field by using endTime as it's name.
By default, Eloquent will convert the created_at, updated_at, and
deleted_at columns to instances of Carbon, which provides an
assortment of helpful methods, and extends the native PHP DateTime
class. You may customize which fields are automatically mutated, and
even completely disable this mutation, by overriding the getDates
method of the model.
Add this method in your model:
public function getDates()
{
return array('created_at', 'updated_at', 'deleted_at', 'endTime');
}
Laravel will take care of these fields and by default each of these fields will be an instance of Carbon object. Read about date mutators. In this case all methods of Carbon could be used on these fields.
Related
In laravel 5.4, I'm able to retrieve fillable fields by using fillable index of model instance.
$model = new AnyClass();
dd($model['fillable']);
The above code prints all fillable fields of AnyClass. But the same code prints null on laravel 5.6. I know I can retrieve fillable fields using $model->getFillable(). My question is what is the reason / why it is not working in laravel 5.6 but works in 5.4?
From the upgrade guide here I believe this is the answer to the question:
Model Methods & Attribute Names
To prevent accessing a model's private properties when using array access, it's no longer possible to have a model method with the same name as an attribute or property. Doing so will cause exceptions to be thrown when accessing the model's attributes via array access ($user['name']) or the data_get helper function.
If you look at Laravel's source code you'll see the difference.
The Model class, which is extended by the application models, implements the ArrayAccess interface, which, among others, force the class to define the offsetGet method.
In Laravel 5.4 the offsetGet method looks like:
public function offsetGet($offset)
{
return $this->$offset;
}
which means that if you call $model['fillable'], you actually call $model->offsetGet('fillable') which actually returns the fillable property of the class.
I couldn't find the Laravel 5.6 tag but I'm pretty sure it is the same code as Laravel 5.5.45. In this version the offsetGet method was changed to:
public function offsetGet($offset)
{
return $this->getAttribute($offset);
}
which means that it actually returns the attribute if found or null otherwise.
In Laravel 7, I'm doing this by calling the getFillable method on a new instance of my model. Like so:
$model = new MyModel();
$fillable = $model->getFillable();
Late to the party but I don't like the concept of having to always instance a Model, specially if you're using Eloquent serialization.
Let's say you wanted to build some filters, but wanted to whitelist the columns based on the model's fillable. You don't want to instance an entire model, so you can instead use reflection:
(new ReflectionClass(MyModel::class))->getDefaultProperties()['fillable']
See it working over at 3v4l.org - Here I demonstrate why you potentially wouldn't want to instance this model due to having serialization and always eager loading.
Change the property in the class to public $fillable = [ instead of protected $fillable = [
I have a model with a created_at value defined as a Unix timestamp.
I retrieve an instance of my model with $model = Model::where(...)->first()
When I var_dump($model->created_at) I get a Illuminate\Support\Carbon instance instead of my integer timestamp.
According to the documentation (emphasis mine):
By default, Eloquent will convert the created_at and updated_at columns to instances of Carbon, which extends the PHP DateTime class to provide an assortment of helpful methods. You may customize which dates are automatically mutated, and even completely disable this mutation, by overriding the $dates property of your model
I've tried adding protected $dates = [] to my model, but I still get the Carbon object instead of an integer.
If I disable timestamps (public $timestamps = false;) it works, but then I won't get my timestamp inserted when I create new entries - and I need that.
Have you tried using:
protected $casts = [
'created_at' => 'integer'
];
i have date as a timestamp in database and i want to convert timestamp into date while fetching data from database, after that want to filter data according to current month wise.
I'm new laravel
In Your eloquent model add this property (more info here):
protected $dates = ['column_name'];
It will be automatically wrap in Carbon
For Example
use Illuminate\Database\Eloquent\Model;
class ExampleModel extends Model
{
protected $dates = ['start_date', 'end_date'];
}
For filter data by month use
ExampleModel::whereMonth('start_date', '12')->get();
I'm trying to create a sort of global mutator for any date string that is retreived from the database.
Now this is probably the wrong way of going about it (and doesn't even work), but I created a class called App\Http\Mutators\ModelMutator which extends Eloquent\Model.
I then changed the Eloquent alias in app.php to point to this new class.
Here is the code for the new class:
<?php
namespace App\Http\Mutators;
use Illuminate\Database\Eloquent\Model;
class ModelMutator extends Model
{
function getAttributeValue($key)
{
$value = parent::getAttributeValue($key);
if (strtotime($value)) {
$value = tolocal($value);
}
return $value;
}
}
This isn't working at all. In fact it appears it isn't even getting called whenever something is retrieved from the database.
I just want to have any date string retrieved from the database to apply the tolocal function.
My biggest issue is I am using packages outside of the App\ namespace and do not want to have to write mutators and modify every single package extends Model class.
Eloquent already has this functionality. Use the $dates property:
protected $dates = [
'created_at',
'updated_at',
'deleted_at'
];
By default, Eloquent will convert the created_at and updated_at columns to instances of Carbon, which extends the PHP DateTime class to provide an assortment of helpful methods. You may customize which dates are automatically mutated, and even completely disable this mutation, by overriding the $dates property of your model
https://laravel.com/docs/5.4/eloquent-mutators#date-mutators
So I have a model, Post that has no methods defined within it.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use DB;
class Post extends Model
{
}
From a controller, I make calls to that model like:
return view('pages.post', ['post' => Post::where('url_route', '=', $url_route)->first()]
This works fine, but I now want to format the date column that is returned from that request, every time that model is called. Is there a way to modify the returned array without defining a new method?
I am new to Laravel to thanks for the help. Just trying to figure out the most efficient way of doing things within the framework...
If your model has $timestamps set to true, the created_at and updated_at fields are natively a Carbon instance.
This means you can format the date in the view like this as a basic example:
$post->updated_at->format('Y-m-d H:i:s')
Carbon instances allow you to leverage its extensive api as you can see at http://carbon.nesbot.com
If you would like to do the same for another field other than created_at and updated_at, you can add an extra property in your model:
protected $dates = ['added_on']
The fields you specify in the array will be treated as Carbon instances.