I've used null UPDATED_AT
contant in models where there were no updated_at
column but something was changed in 5.5 and I couldn't find this change in changelog. In 5.4 updated_at
column was completely ignored on null
value of constant. And now we have an exception:
Too few arguments to function Illuminate\Database\Eloquent\Model::setAttribute(), 1 passed
That happens because setAttribute
method instead of updated_at
column key receives empty string.
Found by @xdisplayx in one of my packages: https://github.com/cybercog/laravel-likeable/issues/24
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEntitiesTable extends Migration
{
public function up()
{
Schema::create('entities', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamp('created_at')->nullable();
});
}
}
<?php
namespace App;
class Entity extends \Illuminate\Database\Eloquent\Model
{
const UPDATED_AT = null;
protected $fillable = [
'name',
];
}
$entity = Entity::create([
'name' => 'Test',
]);
Too few arguments to function Illuminate\Database\Eloquent\Model::setAttribute(), 1 passed
Temporal fix
change const UPDATED_AT = null; to public $timestamps = false;
and set manually data to created_at or in BD set default current_timestamp() to created_at column.
It works for me.
I am not sure from where you got that idea to define const UPDATED_AT = null
.
It was worked fine since 5.0 :} Just experimented myself.
@Manfred047 Thanks for the possible solution, but I'll prefer to add updated_at
column for my case. There is no possibility to update records in my case, but I don't want to add one more hacky fix for it. It seems Laravel not designed to work with single created_at
timestamp.
Actually the suggestion is the least hacky thing here. Laravel provides a simple way to add created_at and updated_at fields to your models. If you need something different, then the solution is to implement it yourself. In Laravel, you do this by setting $timestamps to false on your model then implement your own fields.
try with setAttribute, example
in your model
public function setCreatedAtAttribute($value) {
$this->attributes('created_at') = \Carbon\Carbon::now();
}
remember set $timestamps = false;
@Manfred047 if you are setting $timestamps = false
then setCreatedAtAttribute
method wouldn't be called automatically. And you've got a small issue with attributes assigning in code block, here is how it should looks like:
public function setCreatedAtAttribute($value)
{
$this->attributes['created_at'] = \Carbon\Carbon::now();
}
As @devcircus said there is a possiblity to create special trait which will fill created_at
attribute on model saving
event. That seems to be clean and transparent solution.
Hah... one more hack found. Just add to your model this method and keep $timestamps = true
.
public function setUpdatedAt($value)
{
return $this;
}
Thanks to all of you guys for helping to find all possible ways to solve an issue. As for me this issue could be closed because null UPDATED_AT
constant was worked for a long time but wasn't documented ever.
It wouldn't be hard to extend current HasTimestamps
trait to omit updated_at
Model's attribute but that's another story. Something like:
public $withoutUpdatedAt = true;
I pointed out the breaking change on the following PR but never got any reply xD
@kamui545 I've proposed a solution to stop people using such hacks and standartize models without updated_at
column: https://github.com/laravel/framework/pull/20930 but there is no plans to add this functionality.
Yup I thought so, this is why I ended up adding those fields even if I don't use it.
Thanks for letting me know.
It's very odd const UPDATED_AT = null
is no more a thing, I was using like so a lot in my models, where I do not need updated_at column...
@linaspasv you can find solution above: https://github.com/laravel/framework/issues/20901#issuecomment-326713868
This should work in all 5.x versions.
@a-komarev yes, I have tried it, but it does not seem to work for update actions, still getting - "message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list'
.
const UPDATED_AT = null; was so elegant workaround...
oh it seems, I need to write like this now (const UPDATED_AT = null was missing)
public $timestamps = true;
const UPDATED_AT = null;
public function setUpdatedAt($value)
{
return $this;
}
You don't need $timestamps
property because it's true
by default. And remove UPDATED_AT
constant declaration.
Result should be:
public function setUpdatedAt($value)
{
return $this;
}
@a-komarev without UPDATED_AT constant it doesn't work. :-)
Seems strange. It works for me and @rodrigopedra confirmed this solution too: https://github.com/laravel/framework/issues/21045#issuecomment-327593582
Here is live example: https://github.com/cybercog/laravel-likeable/blob/master/src/Models/Like.php#L52
Hi, @a-komarev in your package works but I also try with that solution in a model of its own and it does not work. I have the same problems as @linaspasv
I am running a simple model without update_at field. Without const UPDATED_AT = null
it still tries to update the missing field.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Fingerprint extends Model
{
protected $table = 'fingerprints';
protected $casts = [
'snapshot' => 'array'
];
const UPDATED_AT = null;
public function setUpdatedAt($value)
{
return $this;
}
}
It seems that there is something that influences. In a new installation if the solution works, but in my project already advanced does not work.
public function up()
{
Schema::create('tests', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamp('created_at')->nullable();
});
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Test extends Model
{
protected $fillable = [
'name',
];
public function setUpdatedAt($value)
{
return $this;
}
}
Route::get('test', function () {
$test = new \App\Test();
$test->name = 'tutututu';
$test->save();
dd($test);
});
The above example works on a new installation.
Sad this breaking change wasn't mentioned :/
@mr-feek it should work again in the next minor release as of #21178 PR
When a hack quits working it doesn't qualify as a breaking change.
Yep. This feature wasn't documented somewhere. So it could be classified as bug.
There are many undocumented features that are only found when reviewing the source code of the framework. Github is a good source to learn new things.
Most helpful comment
There are many undocumented features that are only found when reviewing the source code of the framework. Github is a good source to learn new things.