封裝一個簡單的樂觀鎖方法 -基於Laravel 8

0x5dc0發表於2022-10-04
    /**
     * @function 實現一個簡單的laravel樂觀鎖
     * @return   int 受影響的函式
     * @other    void
     */
    public function cas() {
        //首先判斷資料是否存在
        if(! $this->exists) {
            return 0;
        }

        //獲取那些資料是被更改的
        $changed_but_no_save = $this->getDirty();
        if(! $changed_but_no_save) {
            return 0;
        }

        //判斷更改的欄位和查詢的欄位是否一致
        // array_keys($this->original) 相當於select的欄位
        if(array_diff(array_keys($changed_but_no_save), array_keys($this->original))) {
            return 0;
        }

        //判斷是否要更新時間戳
        if($this->usesTimestamps()) {
            $this->updateTimestamps();
            $changed_but_no_save = $this->getDirty();
        }


        //獲取更新時間欄位的欄位名
        $update_field_name = $this->getUpdatedAtColumn();
        $updated_at_val = $this->{$update_field_name};
        $query = $this->query()->where($this->getKeyName(), $this->getKey())
        ->when($updated_at_val, function (Builder $query) use($update_field_name, $updated_at_val) {
            $query->where($update_field_name, $updated_at_val);
        });

        foreach($changed_but_no_save as $k => $v) {
            //getOriginal(field) 源資料
            $query->where($k, $this->getOriginal($k));
        }
        $res = $query->update($changed_but_no_save);

        //同步Eorm物件資料
        if($res > 0) {
            $this->syncChanges();
            $this->syncOriginal();
        }

        return $res;
    }
$res = ModelName::find($id);
$res->field_name = value;
dd($res->cas());
//在app/Providers/AppServiceProvider.php 的boot方法中寫入以下事件(laravel底層利用觀察者模式記錄SQL到日誌)
DB::listen(function ($query) {
    Log::channel('db')->info($query->sql, $query->bindings);
});

//附config/logging.php配置:
'db' => [
  'driver' => 'daily',
  'path' => storage_path('logs/db.log'),
  'level' => env('LOG_LEVEL', 'debug'),
  'days' => 7,
],


/*
示例日誌
[2022-10-04 01:07:48] local.INFO: select * from `test` where `test`.`id` = ? limit 1 [1] 
[2022-10-04 01:07:48] local.INFO: update `test` set `s1` = ? where `id` = ? and `s1` = ? [6,1,"2"]
*/
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章