小ネタ。ちょっとハマったので。
「patchEntityをして、差分があったときだけsave()に入る」みたいな処理を書きたかった。cake3始めたばかりの頃。
$post = $this->PostsTable->get(1); $post = $this->PostsTable->patchEntity($post, $this->request->getData(); if ($post->isDirty()) { $this->PostsTable->saveOrFail($post); }
のような。
問題は、 isDirty()
の挙動というか。
dirty
となるのは 正しく、更新されたフィールドがあるとき`である。
何を意味するか。
すなわち、 更新しようと思ったフィールドが、全て「適切でなかったとき」、ditryとはならない** 。
たとえば、「ブログ(post)のタイトルを更新しようとした「posts.titleには「最大30文字」のバリデーションがかかっている」「40字のタイトルを付けて更新ボタンをクリック!」というケース。
これは、 marshal()
が完了する前に拒絶され、「patchEntity()
の結果得られる$post->title
」は 以前のままである。その点において、isDirty()
はfalseのまま。
(むしろ汚れてるけどねー)
Table::save()
の中を追うと、 「isNew()
である」もしくは「isDirty()
である」のチェックが行われている。なので、「更新すべきフィールドがあったら〜」なんて処理、思い切ってsave()
にたくしてしまって良い。
$post = $this->PostsTable->get(1); $post = $this->PostsTable->patchEntity($post, $this->request->getData(); try { $this->PostsTable->saveOrFail($post); } catch (\Cake\ORM\Exception\PersistenceFailedException $e) { $entity = $e->getEntity(); $errors = $entity->getErrors(); // $errorsをさばく }
くらいなもんである。