TL;DR: beforeSaveでassociatedを書き換えるときは、ドット記法は使えないので配列で指定する。
Authors
hasMany Posts
hasMany Comments
のリレーションがあるとする。
Authorsから、Posts、Commentsをまとめてsaveしたい場合、通常のsaveであればassociated
に指定してやればよい。
$this->Authors->save($author, [
'associated' => ['Posts.Comments'],
]);
通常はこれでよいとして、特殊な要件により通常はPostsまでの保存で、あるときだけCommentsも保存すると言った場合、Model.beforeSave
イベントにフックしてassociatedを書き換えることを検討する。
単純に以下のコードでは動かない。
// Listenerクラスで
public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)
{
$table = $event->getSubject();
if ($table instanceof AuthorsTable) {
$options['associated'][] = 'Posts.Comments';
}
return true;
}
上記だと InvalidArgumentException : Cannot save Posts.Comments, it is not associated to Authors
と怒られる。
なぜならば associated
オプションはbeforeSaveに入る前に正規化されているため、ドット記法ではなく以下のように配列化しておく必要がある。
public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)
{
$table = $event->getSubject();
if ($table instanceof AuthorsTable) {
$options['associated']['Posts'][] = 'Comments';
}
return true;
}