Reputation: 5286
I want to update a field (status
) on the model. I would retrieve from DB and assign a new value to status
column. But after the model saved, I saw another date field (published_at
) also changed to same as updated_at
.
The action run when user click on a link as http://localhost/dashboard/gallery/publish/1.
I don't know why the published_at
updated auto and same as updated_at
?
Here is Controller code:
<?php
class GalleryController extends Controller
{
/**
* Approve to publish the gallery on the web.
*
* @param int $id
* @return Response
*/
public function getPublish($id)
{
$gallery = Gallery::whereId($id)->firstOrFail();
$gallery->status = Gallery::STT_PUBLISH;
$gallery->save();
return redirect( route('backend::gallery.edit',[$gallery->id]) )->with('status', 'Done');
}
}
?>
and Gallery Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Gallery extends Model
{
use SoftDeletes;
protected $table = 'gallery';
protected $fillable = ['title', 'slug', 'content', 'category_id', 'type'];
protected $guarded = ['published_at','creator_id','thumbnail'];
protected $dates = ['deleted_at', 'published_at'];
}
?>
and Migration func:
public function up()
{
Schema::create('gallery', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->string('slug')->unique();
$table->tinyInteger('type')->unsigned();
$table->integer('category_id')->unsigned()->default(0);
$table->string('thumbnail');
$table->string('title');
$table->text('content');
$table->integer('status')->unsigned()->default(0);
$table->timestamp('published_at');
$table->integer('creator_id')->unsigned();
$table->timestamps();
$table->index(['slug']);
$table->softDeletes();
});
Schema::table('gallery', function (Blueprint $table) {
$table->foreign('category_id')->references('id')->on('category');
$table->foreign('creator_id')->references('id')->on('users');
});
}
UPDATE
I see this config in Migration function makes problem, here:
$table->timestamp('published_at');
And this statement creates SQL like that:
CREATE TABLE `gallery` (
...
`published_at` Timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
...
)
So, how to set up a timestamp field, which is not auto update on current time?
UPDATE 2
Done, I modify the migration, just use dateTime
instead of timestamp
.
Use it, $table->dateTime('published_at');
, this statement will not auto update on CURRENT_TIMESTAMP.
Upvotes: 17
Views: 12844
Reputation: 143
this drove me crazy
it's not a Laravel thing
just go to your PHP my admin -> database -> table -> structure
you will find that this column has an Extra attribute of "on update current_time_stamp" Click change then go to attributes change it to the empty option and save
Upvotes: 0
Reputation: 5030
This is not a problem of Laravel, but a "feature" of MySQL.
According to the reference manual MySQL 5.6
TIMESTAMP and DATETIME columns have no automatic properties unless they are specified explicitly, with this exception: If the explicit_defaults_for_timestamp system variable is disabled, the first TIMESTAMP column has both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP if neither is specified explicitly.
The official site removed reference manual for older version, but when I google for the problem, from the sources that also mention about the problem, it seems that the feature was there for older version of MySQL too.
Therefore, instead of changing $table->timestamp('published_at');
to $table->dateTime('published_at');
, you may also try to solve the problem by
$table->timestamp('published_at')->default(DB::raw('CURRENT_TIMESTAMP'));
or $table->timestamp('published_at')->nullable()
(where the default value is null)$table->timestamps();
so that pulibhsed_at
is not the firs timestamp. The default created_at
and updated_at
is nullable (i.e. having default value null) an will not trigger the "feature"Upvotes: 3
Reputation: 21
There is no need to change migration to
$table->dateTime('published_at');
Just make it
$table->timestamp('published_at')->nullable();
To display the date, you can use something like this in your model
public function getShortDateTimeFromTimestamp($value)
{
if(isset($value))
{
$date = date_create();
date_timestamp_set($date, $value);
return date_format($date, 'd-m-Y H:i');
}
return false;
}
In the view
Published {{ $post->getShortDateTimeFromTimestamp($post->published_at) }}
To use current timestamp when storing/updating the resource, you can use
published_at = \Carbon\Carbon::now();
Upvotes: 1
Reputation: 121
This Post is old but for anyone who got this problem here is the simplest solution. In your migration the timestamp field just has to be nullable. Than there will no auto update trigger on this field.
$table->timestamp('published_at')->nullable();
No need for using $table->dateTime()
instead of $table->timestamp()
.
Upvotes: 12
Reputation: 559
Alternative solution is to create a migration that run this query to remove the ON UPDATE trigger of the column:
ALTER TABLE queued_posts CHANGE scheduled_publish_time scheduled_publish_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
Upvotes: -1
Reputation: 2712
It looks like what is happening is that MySQL (or whichever database you are using) is updating the date, not Laravel.
You need to change:
$table->timestamp('published_at');
to:
$table->dateTime('published_at');
Then do a php artisan migrate:refresh
to rollback and recreate your tables.
Upvotes: 15