Laravel 自動記錄資料建立者/更新者/刪除者 – 波林部落客

image 17

如果在Laravel 中使用時間戳功能,那麼在建立或更新模型時,它會在created_at 和update_at 欄位自動記錄當時建立或更新的時間。如果希望對自訂 created_by 和 updated_by 欄位實現根據登入使用者的 ID 自動更新的功能,則可以在建立 Traits 的檔案如下即可。

<?php

namespace App\Traits;

trait CreatedUpdatedBy
{
    public static function bootCreatedUpdatedBy()
    {
        // updating created_by and updated_by when model is created
        static::creating(function ($model) {
            $userId = auth()?->user()?->id ?? 1;

            if (!$model->isDirty('created_by')) {
                $model->created_by = $userId;
            }
            if (!$model->isDirty('updated_by')) {
                $model->updated_by = $userId;
            }
        });

        // updating updated_by when model is updated
        static::updating(function ($model) {
            $userId = auth()?->user()?->id ?? 1;

            if (!$model->isDirty('updated_by')) {
                $model->updated_by = $userId;
            }
        });
    }
}

這方法依據(Laravel 的 SoftDeletes 特性)可以節省大量時間。 Laravel 的 Eloquent 模型將使用模式 boot[TraitName] 的名稱來啟動特徵的方法。如果您查看 Laravel 的程式代碼,您可以找到下面的程式碼片段。

    /**
     * Create a new Eloquent model instance.
     *
     * @param  array  $attributes
     * @return void
     */
    public function __construct(array $attributes = [])
    {
        $this->bootIfNotBooted();

        $this->initializeTraits();

        $this->syncOriginal();

        $this->fill($attributes);
    }

    /**
     * Check if the model needs to be booted and if so, do it.
     *
     * @return void
     */
    protected function bootIfNotBooted()
    {
        if (! isset(static::$booted[static::class])) {
            static::$booted[static::class] = true;

            $this->fireModelEvent('booting', false);

            static::booting();
            static::boot();
            static::booted();

            $this->fireModelEvent('booted', false);
        }
    }
    /**
     * Perform any actions required before the model boots.
     *
     * @return void
     */
    protected static function booting()
    {
        //
    }

    /**
     * Bootstrap the model and its traits.
     *
     * @return void
     */
    protected static function boot()
    {
        static::bootTraits();
    }
    /**
     * Boot all of the bootable traits on the model.
     *
     * @return void
     */
    protected static function bootTraits()
    {
        $class = static::class;

        $booted = [];

        static::$traitInitializers[$class] = [];

        foreach (class_uses_recursive($class) as $trait) {
            $method = 'boot'.class_basename($trait);

            if (method_exists($class, $method) && ! in_array($method, $booted)) {
                forward_static_call([$class, $method]);

                $booted[] = $method;
            }

            if (method_exists($class, $method = 'initialize'.class_basename($trait))) {
                static::$traitInitializers[$class][] = $method;

                static::$traitInitializers[$class] = array_unique(
                    static::$traitInitializers[$class]
                );
            }
        }
    }        

上面的程式碼告訴我們,名為 boot[traitName] 的特徵也會在模型啟動時被呼叫。

了解了這一點,就可以使用 bootCreatedUpdatedBy 方法建立一個名為 CreatedUpdatedBy 的新特徵,如下所示。

<?php

namespace App\Traits;

trait CreatedUpdatedBy
{
    public static function bootCreatedUpdatedBy()
    {
        // updating created_by and updated_by when model is created
        static::creating(function ($model) {
            $userId = auth()?->user()?->id ?? 1;

            if (!$model->isDirty('created_by')) {
                $model->created_by = $userId;
            }
            if (!$model->isDirty('updated_by')) {
                $model->updated_by = $userId;
            }
        });

        // updating updated_by when model is updated
        static::updating(function ($model) {
            $userId = auth()?->user()?->id ?? 1;

            if (!$model->isDirty('updated_by')) {
                $model->updated_by = $userId;
            }
        });
    }
}

接下來,就可以輕鬆地在任何應用它的模型中使用它,就像使用 SoftDeletes 特性一樣。例如在的 Post 方法中,它應該看起來像這樣。

<?php

namespace App\Models;

use App\Traits\CreatedUpdatedBy;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use CreatedUpdatedBy;

}

參考:

Automatically Update `created_by` and `updated_by` in Laravel Using Bootable Traits

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *