laravel的Eloquent非常好用,可以自动维护created_at和updated_at两个字段,但是实际场景中可能同一个请求中更新多张表,而created_at时间不一致的情况
    例如:

    1. //foo表新增数据
    2. Foo::query()->create();
    3. //假装耗时操作...
    4. sleep(3);
    5. //bar表中新增数据
    6. Bar::query()->create();

    结果foo表和bar表的created_at相差3秒
    那么这种问题如何解决呢,
    laravel的每个包扩展性都非常强,如果能找到Eloquent源码中维护created_at字段的方法,就不必在上层处理。

    在Illuminate\Database\Eloquent\Model中可以看到使用了HasTimestamps这个trait来时间时间戳,

    1. abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
    2. {
    3. use Concerns\HasAttributes,
    4. Concerns\HasEvents,
    5. Concerns\HasGlobalScopes,
    6. Concerns\HasRelationships,
    7. Concerns\HasTimestamps,//处理自动维护时间戳
    8. Concerns\HidesAttributes,
    9. Concerns\GuardsAttributes,
    10. ForwardsCalls;
    11. ...
    12. ...

    那么继续,
    在Illuminate\Database\Eloquent\Concern\HasTimestamps中找到

    1. /**
    2. * Update the creation and update timestamps.
    3. *
    4. * @return void
    5. */
    6. protected function updateTimestamps()
    7. {
    8. $time = $this->freshTimestamp();//获取时间戳
    9. if (! is_null(static::UPDATED_AT) && ! $this->isDirty(static::UPDATED_AT)) {
    10. $this->setUpdatedAt($time);
    11. }
    12. if (! $this->exists && ! is_null(static::CREATED_AT) &&
    13. ! $this->isDirty(static::CREATED_AT)) {
    14. $this->setCreatedAt($time);
    15. }
    16. }
    1. /**
    2. * Get a fresh timestamp for the model.
    3. *
    4. * @return \Illuminate\Support\Carbon
    5. */
    6. public function freshTimestamp()
    7. {
    8. return Date::now();//就是这里了
    9. }

    那么只要重写这个方法就好了,所以定义个一个trait
    这里使用了变量容器,相关参考laravel技巧—变量容器

    1. namespace App\Model;
    2. use App\Light\Box\Box;
    3. use App\Light\Box\BoxContainer;
    4. trait KpHasTimestamps
    5. {
    6. public function freshTimestamp()
    7. {
    8. //获取当前请求时间戳常量
    9. return Box::get(BoxContainer::NOW);//变量容器
    10. }
    11. }

    在模型Foo中使用KpHasTimestamps

    1. namespace App\Model;
    2. use Illuminate\Database\Eloquent\Model;
    3. class Foo extends Model
    4. {
    5. //使用新定义维护时间戳的方法
    6. use KpHasTimestamps;
    7. protected $primaryKey = 'id';
    8. protected $table = 'foo';
    9. protected $guarded = [];
    10. }

    在模型Bar中也使用KpHasTimestamps

    1. namespace App\Model;
    2. use Illuminate\Database\Eloquent\Model;
    3. class Bar extends Model
    4. {
    5. //使用新定义维护时间戳的方法
    6. use KpHasTimestamps;
    7. protected $primaryKey = 'id';
    8. protected $table = 'bar';
    9. protected $guarded = [];
    10. }

    现在再执行最开始的两条create代码,查看表中created_at时间一致了。