事象
CakePHPで、カスタムバリデーションが動作しない自体が発生しました。
コードを追いかけると以下のようなコードでした(元のコードを元にサンプル作成)
// 記事を公開するかどうか
$isPublish = $this->request->getData('is_publish');
// 該当記事のEntityを取得
$articles = $this->Articles->get($page);
// 公開・非公開の情報をEntityにセット
$articles->is_publish = $isPublish;
// DBに保存
$this->Articles->save($articles);
一見間違いなさそうに見えますが、CakePHPでは、newEntityまたはpatchEntity実行時にしかカスタムバリデーションが発火しないとのこと。
解決方法
CakePHPでは、newEntityまたはpatchEntity実行時にしかカスタムバリデーションが発火しないので、上記のコードをnewEntityまたはpatchEntityを使って更新してあげればOKでした。
改善例
// 記事を公開するかどうか
$isPublish = $this->request->getData('is_publish');
// 該当記事のEntityを取得
$articles = $this->Articles->get($page);
// DBに保存
$articleEntity = $this->Articles->patchEntity($articles, ['is_publish' => $isPublish]);
$this->Articles->save($articleEntity);
他のバリデーションが邪魔をする場合
単純にバリデーションがかかっているならいいのですが、
例えば「記事のタイトルが必須」などの条件が含まれている場合、上記のコードでは
cakephp patchEntity This field is required
のようなエラーが発生します。
これは、newEntityまたはpatchEntity実行時にバリデーションが実行されるので、更新項目にタイトルが含まれていないから起こります。
このような場合は、全データを追加してあげることで回避できそうです。
// 記事を公開するかどうか
$isPublish = $this->request->getData('is_publish');
// 該当記事のEntityを取得
$articles = $this->Articles->get($page);
// 全データを配列に
$articleArray = $articles->toArray();
// 更新したい要素を上書きする
$articleArray['is_publish'] = $isPublish;
// DBに保存
$articleEntity = $this->Articles->patchEntity($articles, $articleArray);
$this->Articles->save($articleEntity);
以上です