LoginSignup
4
3

More than 3 years have passed since last update.

【Laravel】saveメソッドはpkの値がないと正しくupdate処理しない

Last updated at Posted at 2019-12-26

DBにデータを保存するときにお世話になるsaveメソッドでプチハマりした時の小ネタ
また同じことでハマらないように。

前置き

環境はLaravel5.7

何をしようとしたか

DB上のitemsテーブルにある決まった条件下のデータに対し、1つのカラムの値をupdateしたかったのでこんなコードを書きました。
カラム数の多いテーブルだったので、select時に取得するカラムを処理の中で使用するもののみに限定していました。

TestController.php
    // 更新するデータを取得
    $updateItemId = 'xxxxxx';
    $item = Item::select('item_id')->where('item_id', $updateItemId)->first();

    // 更新
    $item->status = true;
    $item->save();

しかし更新されない…トランザクションはってるけどコケてない…
何故?

そしてこれなら正しく更新される

TestController.php
    // 更新するデータを取得
    $updateItemId = 'xxxxxx';
    $item = Item::where('item_id', $updateItemId)->first();

    // 更新
    $item->status = true;
    $item->save();

ライブラリを見てみよう

フレームワークの機能で詰まったらググるかライブラリを掘る。
saveメソッドの処理はライブラリの
laravel/framework/src/Illuminate/Database/Eloquent/Model.php
こいつの中で行なっている模様。
saveメソッドを見つけて中を読んでみると、同じModel.phpのperformUpdateメソッドを呼び出している。
dd関数を駆使してどこで引っかかっているか検証していくと、updateメソッドを呼び出すところまでは順調だった。
で、肝心のupdateがここ!

laravel/framework/src/Illuminate/Database/Eloquent/Model.php
    $this->setKeysForSaveQuery($query)->update($dirty);

このsetKeysForSaveQueryが何をしているかというと、クエリのwhere句を作っている。

laravel/framework/src/Illuminate/Database/Eloquent/Model.php
    protected function setKeysForSaveQuery(Builder $query)
    {
        $query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery());

        return $query;
    }

Model.phpの中で、getKeyNameメソッドではPKであるidを、getKeyForSaveQueryはupdate対象の行のidの値を返している。
idの値がなければnullが返されているので、ここで生成されているwhere句は

where `id` = null

となる。id = nullの条件に合致するデータはないので、updateすることなく処理が終わっていた。。
where句の条件がidで固定されているので更新するデータを取得する時点でidカラムも取得しないとだめか…

解決方法

結局こうしました
安直ですが他に方法が思いつかず。

TestController.php
    // 更新するユーザーを取得
    $updateItemId = 'xxxxxx';
    $item = Item::select('id', 'item_id')->where('item_id', $updateItemId)->first();

    // 更新
    $item->status = true;
    $item->save();

無事更新。
コード書くのもいいけどライブラリの処理追っていくのも楽しいです

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3