为什么 Laravel 5 会自动更新我的日期字段?

Why does Laravel 5 auto update my date field?

我想更新模型上的字段 (status)。我将从数据库中检索并为 status 列分配一个新值。但是模型保存后,我看到另一个日期字段 (published_at) 也更改为与 updated_at 相同。 当用户点击 link 作为 http://localhost/dashboard/gallery/publish/1 时的操作 运行。

我不知道为什么 published_at 自动更新并与 updated_at 相同?

这里是控制器代码:

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

图库模型

<?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'];
}
?>

迁移函数:

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

更新

我在迁移功能中看到这个配置有问题,在这里: $table->timestamp('published_at');

并且这个语句创建了 SQL 这样的:

CREATE TABLE `gallery` ( 
    ...
     `published_at` Timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    ...
)

那么,如何设置一个不在当前时间自动更新的时间戳字段?

更新 2

完成,我修改迁移,只用dateTime代替timestamp

使用它,$table->dateTime('published_at');,此语句不会在 CURRENT_TIMESTAMP.

上自动更新

看起来正在发生的事情是 MySQL(或您正在使用的任何数据库)正在更新日期,而不是 Laravel。

您需要更改:

$table->timestamp('published_at');

至:

$table->dateTime('published_at');

然后执行 php artisan migrate:refresh 回滚并重新创建您的表。

替代解决方案是创建一个迁移,运行 此查询删除列的 ON UPDATE 触发器:

ALTER TABLE queued_posts CHANGE scheduled_publish_time scheduled_publish_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP

这个 Post 是旧的,但对于任何遇到此问题的人来说,这里是最简单的解决方案。在您的迁移中,时间戳字段必须可以为空。将不会在此字段上触发自动更新。

$table->timestamp('published_at')->nullable();

无需使用 $table->dateTime() 而不是 $table->timestamp()

无需将迁移更改为

$table->dateTime('published_at');

就这样吧

$table->timestamp('published_at')->nullable();

要显示日期,您可以在模型中使用类似这样的东西

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

在视图中

        Published {{ $post->getShortDateTimeFromTimestamp($post->published_at) }}

要在 storing/updating 资源时使用当前时间戳,您可以使用

published_at = \Carbon\Carbon::now();

这不是Laravel的问题,而是MySQL的"feature"问题。

根据 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.

官方网站删除了旧版本的参考手册,但是当我google解决问题时,从也提到该问题的来源来看,似乎该功能适用​​于旧版本MySQL也是。

因此,除了将$table->timestamp('published_at');改为$table->dateTime('published_at');,您也可以尝试通过

来解决问题
  1. 给时间戳一个默认值。例如$table->timestamp('published_at')->default(DB::raw('CURRENT_TIMESTAMP'));$table->timestamp('published_at')->nullable()(默认值为 null)
  2. $table->timestamps(); 之后移动该行,这样 pulibhsed_at 就不是第一个时间戳。默认的 created_atupdated_at 可以为空(即默认值为 null),不会触发 "feature"