どういうこと?
有効であるか論理削除されているか存在しないかいずれかわからない状態のレコードがあるけど、事前の状態に関わらず有効にして保存したい。
というわけでこんなかんじのクエリを実行したわけですよ。
class Hoge extends Model{
use SoftDeletes;
}
$model = Hoge::withTrashed()->firstOrNew(['id'=>999]);
$model->foo = 'bar';
$model->restore();
$model->save();
これ、論理削除されたレコードがあれば論理削除が解除されてきちんと有効になりますが、存在しないレコードはINSERTされません。
なんで??????
エラーは出ないしrestore()
もsave()
もtrueを返してくるから正しく動いたと勘違いするじゃないですか。
正解はこうです。
$model = Hoge::withTrashed()->firstOrNew(['id'=>999]);
$model->foo = 'bar';
$model->save();
$model->restore();
そんなんわかるか!
save()
は保存時に元のデータと保存するデータで差分があるかをチェックし、差があるときだけ更新します。
restore()
すると削除フラグを消してデータを保存し、その差分をリセットします。
困ったことに、まだDB上に存在しないレコードだった場合は、差分をリセットするけどデータの保存はしません。
そのせいで、save()
したときに差分がないから保存しないと判断されてしまいました。
ということで試していませんが、順番を変える以外にもfirstOrNew()
のかわりにfirstOrCreate()
を使うと正しく動くと思います。
firstOrNew()
はレコードが存在しなければ作成する、ただしDBには保存しない。
firstOrCreate()
はレコードが存在しなければ作成し、DBに保存まで行う。
なので最初にfirstOrCreate()
しておけば、restore()
時には既にレコードが存在するから更新してくれるというわけです。
まとめ
restore()
がエラーを出さないのが悪い。