はじめに
先日ある機能を実装していた時に、早とちりで「DBが更新されていない!」と慌てた時の話を書いていこうと思います。
実装
DBのHogehoge
レコードのfuga
フラグを変更するという処理を実装しようとしました。
App\Hogehoge
のモデルの$fillable
にfuga
が設定されているという状況下で、まずHogehogeRepository
クラスにフラグ変更用のメソッドを記述しました。
App\Repositories\HogehogeRepository.php
<?php
namespace App\Repositories;
use App\Hogehoge;
class HogehogeRepository
{
private $hogehoge;
public function __construct(Hogehoge $hogehoge)
{
$this->hogehoge = $hogehoge;
}
public function setFugaFlag(int $id)
{
return $this->hogehoge->find($id)->fill(['fuga' => 1])->save();
}
}
このメソッドの動作を確認する為、Tinkerで以下のような動作確認をしました。
$hogehoge = App\Hogehoge::first();
// => App\Hogehoge { #....
// ...
// }
$hogehoge->fuga = 0;
// => 0
$hogehoge->save()
// => true
$repo = app(App\Repositories\HogehogeRepository::class);
// => App\Repositories\HogehogeRepository {#....}
$repo->setFugaFlag($hogehoge->id);
// => true
$hogehoge;
// => App\Hogehoge { #....
// ...
// fuga: 0
// }
すると、値が変更されているはずのところ、変更前の値が出てきました。
なぜこうなったか
Tinkerの中で$hogehoge
の値を設定した後、HogehogeRepository
のメソッドで$hogehoge
に対応するレコードを更新しています。しかし、その後意図的に$hogehoge
を更新しなければ、$hogehoge
に最新のレコードの値は反映されないようでした。
解決方法
変数$hogehoge
は更新されていませんが、対応するDBのレコードは更新されているので、新たにレコードを取得することで確認することができます。
// $repo->setFugaFlag($hogehoge->id);
App\Hogehoge::find($hogehoge->id);
// => App\Hogehoge { #....
// ...
// fuga: 1
// }
また、変数$hogehoge
自体を更新することもできます。
// $repo->setFugaFlag($hogehoge->id);
$hogehoge->refresh();
// => App\Hogehoge { #....
// ...
// fuga: 1
// }
補足
今回Tinkerでモデルオブジェクトが更新されなかったことについて書きましたが、テストコード等Tinker以外の場所のコードでも起こるようです。特にテストコード内では「実際にモデルorDBの値が変更されていることを確認する」という動作を書くことが多そうなので、注意が必要になりそうです。