2017-06-05 53 views
0

当我通过一个联结表将belongs-to-many实体与belongsToMany-> link()函数链接时,联结表上的afterSaveCommit事件不会触发。 link()函数似乎总是在事务中调用save(),并且我无法找到它将在afterSaveCommit之后调用的位置,因为实体没有顶级save()调用。在调用链接()调用中的SaveCommit之后调用

这是一个疏忽还是通过设计?

回答

0

在多次阅读代码并对其进行了深入研究之后,我认为“它应该”的问题在双方都有争论。

我发布我的解决方案,希望它能帮助别人。

我在ElasticSearch存储库中保存非规格化的逻辑记录副本以供分析,目标是在任何参与的关系实体更改时自动同步ES。所有相关实体都使用afterSave触发器来同步ES。核心逻辑记录与静态数据列表有很多belongsToMany关系,所以有很多连接表和对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; 
} 
} 

这迫使相同的行为,其中顶部实体保存后,其在链路()的情况下,是连接表同步时才进行。

我还在那里添加了删除事件,既可以处理unlink()调用,也可以级联删除。

如果这是我们所期望的,我还会采取一种保护措施来彻底改变行为。将其作为行为的静态变量允许它在具有行为的所有实体间共享,即使它们各自具有其自己的事件管理器。