После нескольких шагов по коду и остановившись на нем, я думаю, что вопрос о том, что это «должно быть», имеет аргументы с обеих сторон.
Я публикую свое решение в надежде, что оно поможет кому-то еще.
Я храню денормализованную копию логических записей в репозитории ElasticSearch для анализа, и цель состоит в том, чтобы автоматически синхронизировать ES при изменении любого из участвующих реляционных объектов. Все соответствующие объекты подключили триггер afterSave для синхронизации ES. Базовая логическая запись имеет множество отношений ownToMany со списками статических данных, поэтому множество таблиц соединений и вызовов link(). Запись ES обновлялась после каждого, что занимало слишком много времени.
Я прибегнул к событию afterSave, которое всегда запускается, а затем создал поведение, размещенное во всех соответствующих таблицах, со следующим кодом, который зависит от поведения параметра _primary, установленного в значение true, при сохранении объекта верхнего уровня. Действительно, это одна из подсказок, которую Cake использует, чтобы определить, когда запускать событие afterSaveCommit.
У меня есть опасения по поводу использования недокументированного флага с префиксом подчеркивания, даже если он передается обратно в массиве параметров.
class ElasticSyncBehavior extends Behavior
{
private static $_suspend_flag = false;
public function suspend_elastic_sync() {
self::$_suspend_flag = true;
}
public function resume_elastic_sync() {
self::$_suspend_flag = false;
}
public function afterSave($event, $entity, $options) {
if($options["_primary"]!=true || self::$_suspend_flag==true) {
return $entity;
}
// do synchronization here
return $entity;
}
public function afterDelete(Event $event, EntityInterface $entity, ArrayObject $options) {
if($options["_primary"]!=true || self::$_suspend_flag==true) {
return $entity;
}
// do synchronization here
return $entity;
}
}
Это приводит к такому же поведению, когда синхронизация выполняется только после сохранения верхнего объекта, который в случае link() является таблицей соединения.
Я также добавил туда событие удаления, как для обработки вызовов unlink(), так и для каскадных удалений.
Я также добавил защитный хак, чтобы полностью переопределить поведение, если это то, что нужно. Статическая переменная поведения позволяет использовать ее для всех сущностей, у которых есть поведение, даже если у каждой из них есть собственный диспетчер событий.
25.09.2017