默认内容实体创建流程:
• 执行实体类的preCreate方法
• 为要创建的实体补充uuid值
• 判断bundle值的存在性
• 实例化一个空的实体对象
• 用值初始化实体对象,如果没有提供值,将采用默认值
• 如果提供了没有字段定义的值,也会为实体赋值该属性
• 执行实体类型层面和实体层面的钩子:field_values_init
• 强制实体为新的(即便传了id值也被认为是新的)
• 执行实体对象的postCreate方法
• 执行实体类型层面和实体层面的创建钩子create
创建涉及钩子及执行顺序如下:
• 字段值初始化钩子:$entityTypeId . ‘_field_values_init’ 和’entity_field_values_init’
• 创建钩子:$entityTypeId . ‘_create’ 和’entity_create’
注意创建实体后并不会被自动保存,如需保存需要显式调用save方法
默认内容实体加载流程:
• 如果储存处理器中有静态缓存,那么直接使用静态缓存,否则继续
• 从持久缓存中加载,默认为数据库表cache_entity,若有直接使用
• 从储存中加载实体
• 对id进行消毒处理
• 从基本表和版本表中查询数据
• 如果有数据表及数据版本表则从中加载数据
• 从专用表中加载数据
• 用加载的数据库记录值实例化实体对象
• 执行钩子:entity_storage_load及$entityTypeId . ‘_storage_load’
• 将加载的实体缓存到持久缓存
• 执行实体类定义的postLoad方法
• 执行实体加载钩子entity_load及实体类型加载钩子$entityTypeId . ‘_load’
• 设置储存处理器的静态缓存
加载涉及钩子及执行顺序如下:
• 实体加载钩子 entity_storage_load
• 实体类型储存加载钩子:$entityTypeId . ‘_storage_load’
• 实体加载钩子entity_load
• 实体类型加载钩子$entityTypeId . ‘_load’
注意钩子的执行顺序,这和默认的“先类型层面再实体层面”是相反的
默认内容实体保存流程:
• 开启数据库事务,如果各表不同步可以全部回滚
• 执行保存前逻辑doPreSave:
• 将实体对象各字段对象中为空的条目去除,然后提取值更新内部值数组($values属性)
• 更新版本id
• 执行检查,如果实体已经存在而实体被标记为新,那么抛出错误
• 如果实体存在,那么为$entity->original赋值,其为原始未改变的实体
• 执行实体对象本身的保存前逻辑(preSave方法),默认为检查是否经过数据验证和id是否符合要求
• 执行保存前钩子“presave”(实体类型级别和实体级别两个钩子)
• 执行检查:实体不为新时,id不允许改变;在不建立新版本时不允许版本id改变
• 执行保存逻辑doSave:
• 执行检查:如果在执行保存前逻辑后实体仍然被标记为新,那么执行强制为新(有id也是新)
• 如果实体为新,那么设置为新版本,并将所有翻译的更新旗标置为NULL以表示未进行手工翻译
• 设置翻译更新旗标,如果某翻译有变化设置为true,表示已经进行了手工翻译
• 进行数据库储存,执行sql内容储存处理器的doSaveFieldItems方法,并给新实体的id和版本id赋值
• 执行保存后逻辑doPostSave:
• 执行翻译钩子translation_insert或translation_delete
• 如果实体是可静态缓存的,那么重置实体处理器内部缓存
• 将实体设置为非新
• 执行实体对象的保存后逻辑,默认有失效缓存标签、将移除的翻译删去、将新建的翻译状态改为存在
• 执行更新或插入钩子
• 设置实体原id,也就是执行实体的setOriginalId方法
• 执行unset($entity->original);
• 在以上过程中如果出现异常那么回滚数据库事务,并记录日志,抛出实体储存异常,否则进入后续步骤
• 在从数据库得到更新前禁用从库
• 返回保存状态标识:如果失败为false,否则依据是保存还是更新返回常量SAVED_NEW 或SAVED_UPDATED
保存涉及钩子及执行顺序如下:
• 保存前钩子,钩子名:$entityTypeId . ‘_presave’ 和’entity_presave’
• 保存后翻译钩子:translation_insert或translation_delete
• 更新钩子:$entityTypeId . ‘_update’ 和’entity_update’ 或插入钩子:$entityTypeId . ‘_insert’ 和’entity_insert’ ,这在保存后执行
在执行以上钩子时,如果钩子是:presave、insert、update则会执行实体中字段对象的相应方法,这允许实现一些高级功能,如引用字段、实体保存后字段对象再次更新数据库值
默认内容实体删除流程:
• 开启数据库事务
• 执行实体类的静态方法:preDelete,在节点实体中将删除搜索索引
• 执行删除前钩子predelete
• 执行删除逻辑doDelete
• 执行实体各字段对象的delete()方法
• 执行doDeleteFieldItems方法进行数据库真实删除
• 重置储存处理器的内部缓存
• 执行实体类的postDelete方法
• 执行删除钩子delete
• 删除方法没有返回值
• 以上流程出现异常则回滚数据库,记录日志、抛出实体储存异常
• 在从库得到更新前禁用从库
删除涉及钩子及执行顺序如下:
• 删除前钩子,钩子名:$entityTypeId . ‘_predelete’ 和’entity_predelete’
• 删除后钩子,钩子名:$entityTypeId . ‘_delete’ 和’entity_delete’
默认内容实体版本删除流程:
• 加载实体,如果不存在,则不用删除
• 检查是否为默认版本,默认版本不可被删除,这应在实体上删除,否则数据库将产生碎片数据
• 执行实体字段对象的deleteRevision方法
• 删除版本表数据
• 删除版本数据表数据
• 删除专用表的版本表数据
删除版本涉及钩子及执行顺序如下:
• 删除版本钩子,钩子名:$entityTypeId . ‘_revision_delete’ 和’entity_revision_delete’
实体翻译创建流程:
实体的翻译并不是直接创建的,而要先建立一个源语言的实体对象,然后在这个对象基础上进行建立,因此内容实体基类的createTranslation方法接受一个实体对象,创建流程如下:
• 从源语言实体上得到翻译语言实体
• 过滤出可翻译字段
• 用传入的值初始化翻译语言实体
• 执行翻译创建钩子
翻译创建流程涉及的钩子及执行顺序如下:
• 实体类型翻译创建钩子:$entityTypeId . ‘_translation_create’
• 实体翻译创建钩子:’entity_translation_create’
注意创建的翻译并没有保存,这需要显式调用save方法,在实现翻译创建钩子时需要明白她可能不会被保存