LoginSignup
0
0

CakePHP の beforeSave() で失敗した際、それを何とか検知したい

Posted at

はじめに

この前、弊社 CakePHP4 プロジェクトにて beforeSave() で失敗してしまう不具合がありましたが「見かけ上は save() で失敗しているのに Entity の errors には何のエラーも保存されていない…」という困った状態でした。

しかも beforeSave() の処理そのものは Behavior に書いており、 Table クラスには何も書いてなかったので、beforeSave() の存在に気付くのも遅れました。

なので beforeSave() での失敗を何とか検知したいなと思って調べた結果をメモ。

cookbook を読んでみる

CakePHP4 の cookbook によると

beforeSave

Cake\ORM\Table::beforeSave(EventInterface, EntityInterface, ArrayObject)
Model.beforeSave イベントはエンティティーが保存する前に発行されます。 このイベントを止めることによって、保存を停止できます。イベントが停止すると、 このイベントの結果が返されます。

ちょっと分かりにくいですが、beforeSave() を止める(※falseを返す)と、save() も失敗しますよ。その場合 beforeSave() の結果を返しますよ、というお話かなと思います。

beforeSave() が false を返したので、save() もそれに従い false を返したという感じですかね?だとすると Entity の errors に何も保存されていないのは当然です。そもそも保存処理を実行してないので。

ただそれだと困るので、何とかしたい。

いくつか出た案まとめ

案1 - 例外を出す

シンプルに BeforeSaveException クラスでも作って失敗したら例外を出す、
BeforeSaveException を catch したら、beforeSave() で失敗したね、って判別出来ます。

namespace App\Exceptions;

final class BeforeSaveException
{
    // 略
}
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
    // 略

    throw new BeforeSaveException('beforeSave() に失敗しました');

    // 略
}

ただコレだと BeforeSaveException をキャッチする処理を他のクラスに書く必要があるんですよね

あと beforeSave() に複数のエラー判定ロジックがある場合、それぞれを判別できるようにまた新しく Exception を作るのか、もしくは例外メッセージで判別するのか…みたいな。

案2 - Entity の errors に突っ込む

普通に Entity の setError() メソッドを利用して、errors に突っ込みます。

Entity の errors にエラーが格納されるので、他のクラスに手を加えなくてもエラーを検知出来ます。

public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
    if (
        // 何らかの条件
    ) {
        $entity->setError('beforeSave', 'beforeSave() に失敗しました');
        return false;
    }
}

しかし保存処理を実行してないのに Entity にエラーを突っ込んで良いのか?
というか beforeSave() のエラーは Entity に入れるべきなの?という疑問が残ります…いいのかな

案3 - Entity の errors に何も入ってなかったら beforeSave() のエラーと考える

さすがにちょっと乱暴すぎる気がしますが…プロジェクトの規模によってはアリかも

まとめ

弊社では案1と悩んだ挙げ句案2を採用しました

0
0
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
0
0