[CakePHP3] 特定レコードのsave()が失敗する時はsaveOrFail()を使ってみよう
2020/01/26
masyus
CakePHP3で実装したsave()
がどういうわけかよく失敗することがありました。その際はExceptionもthrowせずにfalseだけを返すため、原因の特定に苦労したことがあります。今回はその解決策を紹介します。
バージョン情報
- PHP: 7.4.33
- CakePHP: 3.6.15
save()が頻繁に失敗するケース
save()
が失敗してfalseが返ってくるケースでは、
何らかの理由でExceptionがthrowされた結果、falseが返却される
ことが多いです。
個人的に頻繁に遭遇したケースでは、save()
を実行したTableクラスにbuildRules()
が設定されており、その外部キー制約に引っかかっていた為にExceptionを吐く条件を満たしていたことがありました。具体的には
$rules->add($rules->existsIn('article_id', 'Articles'));
等です。この制約に引っかかりますとPersistenceFailedExceptionがthrowされます。
saveOrFail()を使おう
このようにExceptionをthrowし、その原因を把握できる状態にしたい場合はsave()
の代わりにsaveOrFail()
を使いましょう。レコードへ保存する処理はsave()
と同じですが、
何らかの制約に引っかかった時にExceptionをthrowしてくれる堅実性がある
ため、try-catchで細かくエラーハンドリングしたい時に便利です。
保存処理は基本的にsave()よりもsaveOrFail()を使うのが良いか?
状況次第ではありますが、例えば
buildRules()
を頻繁に使い、アプリケーションレイヤーで外部キー制約を設定している- レコード保存時の失敗理由を細かくログに吐き出したい
等に該当する場合、保存処理は基本的にsaveOrFail()
を使うのが良いと思います。そこまで厳密に実装しなくても良い場合はsave()
で事足りるかと思います。