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