😸

CakephpのafterMarshal()によるバリデーションエラーの消失

2024/12/19に公開

はじめに

CakePHPでバリデーションエラーになったはずのフィールドのエラーがunsetされる問題が起き、原因がすぐに分からなかったのでまとめておこうと思います

unsetされた原因

afterMarshal()でentityに値をセットしたことが原因でした。
entityにセットした際にsetDirty()が呼ばれ、その中で下記unsetが使われていました

unset($this->_errors[$field], $this->_invalid[$field]);

afterMarshal()ですべてのエラーをunsetして、再度バリデーションを走らせているような動作をしているようにみえましたが、newEntity()patchEntity()のコードをみてもそのような記述がなく、
setDirty()unset()される事も知らなかったのですぐには気づけませんでした。

まとめ

buildRules()で複合ユニークの検証をしたかったのでafterMarshal()で値をセットしましたが、
afterMarshal()の使い方によってはバリデーションのエラーが消える可能性があるので、使い方には注意が必要みたいです。

参考コード

afterMarshal()の記述は下記のようなコードでdate_toにバリデーションエラーがあるはずが特定の場合になくなっていました

public function afterMarshal(Event $event, EntityInterface $entity, ArrayObject $data, ArrayObject $options)
{
    if ($entity->type == 1 || $entity->type == 2) {
        $entity->date_to = $entity->date_from;
    }
}

環境

CakePHP: 4.5

Discussion