CRUD 序列
CRUD 序列。
本文档详细描述 iTop ORM 中 CRUD 操作(创建、更新、删除)的方法调用序列。更多详细内容请参考 iTop 官方文档。
概述
这是 iTop ORM CRUD 栈(创建、更新、删除操作)中方法调用的映射。要了解更多关于扩展性的信息,请参阅扩展性 API。
对象层次结构
iTop 核心中有 3 个类可以扩展用于新的 iTop 对象:
- DBObject:数据库中的持久化对象
- CMDBObject:添加历史跟踪
- cmdbAbstractObject:可编辑对象
所有默认数据模型对象都是 cmdbAbstractObject 的子类。
栈修改历史
- 2.7.0:事务(参见:N°679, N°2456)
- 3.1.0:事件(N°4756, N°5906)
图例说明
- 粗体:可覆盖的回调(在代码中标记为
overwritable-hookPHPDoc 标签) - 红色:直接对数据库执行的操作
- 蓝色:父方法
- 绿色:事件
- 紫色:对象访问修改
DBInsert(创建对象)
从 DBObject::DBInsert 开始:
cmdbAbstractObject::DBInsertDBObject::DBInsertNoReloadDBObject::DoComputeValuescmdbAbstractObject::FireEventComputeValues-EventService::FireEvent(EVENT_DB_COMPUTE_VALUES)(自 3.1.0 N°4756)DBObject::ComputeValuesDBObject::OnInsertcmdbAbstractObject::FireEventBeforeWrite-EventService::FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => true])(自 3.1.0 N°6324)DBObject::CheckToWrite- 如果
MetaModel::SkipCheckToWrite则返回 DBObject::SetReadOnly:从此处起不允许DBObject::Set(自 3.1.0 N°4756)cmdbAbstractObject::FireEventCheckToWrite-EventService::FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => true])(自 3.1.0 N°4756)DBObject::SetReadWrite:从此处起允许DBObject::Set(自 3.1.0 N°4756)cmdbAbstractObject::DoCheckToWrite- 如果
CheckToWrite返回 false,则抛出CoreCannotSaveObjectException DBObject::GetState- 遍历
MetaModel::ListAttributeDefs,如果$oAttDef instanceof AttributeStopWatchormStopWatch::StartormStopWatch::ComputeDeadlines
DBObject::Set:设置具有修改值的属性CMDBSource::Query('START TRANSACTION')(自 2.7.0 N°679)DBObject::DBInsertSingleTable($sRootClass)DBObject::DBInsertSingleTable($sClass):在叶类上调用插入- 遍历
MetaModel::EnumParentClassesDBObject::DBInsertSingleTable($sParentClass):在类层次结构上调用插入
cmdbAbstractObject::OnObjectKeyReadyInlineImage::FinalizeInlineImagesDBObject::DBWriteLinks- 遍历每个修改的 linkset
ormLinkSet::DBWrite
DBObject::WriteExternalAttributes\AttributeCustomFields::WriteExternalValues
CMDBObject::RecordObjCreation- 删除删除记录
- 删除 2.0.3 之前遗留的任何其他更改跟踪信息
DBObject::RecordObjCreationDBObject::RecordLinkSetListChange- 创建新的
CMDBChangeOpCreate
CMDBSource::Query('COMMIT')(异常时 ROLLBACK)- 重置元信息:
m_bIsInDB = true,m_bDirty = false,设置m_aOrigValues[$sAttCode] MetaModel::StartReentranceProtection()(自 3.1.0 N°4756)cmdbAbstractObject::PostInsertActionsDBObject::PostInsertActionscmdbAbstractObject::FireEventAfterWrite\cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification(自 3.1.0 N°5906)\cmdbAbstractObject::FireEventDbLinksChangedForCurrentObject-EVENT_DB_LINKS_CHANGED(自 3.1.0 N°5906)EventService::FireEvent(EVENT_DB_AFTER_WRITE, ['changes' => [], 'is_new' => true])(自 3.1.0 N°6324)DBObject::AfterInsert
- 搜索触发器:
$sClassList = MetaModel::EnumParentClassesSELECT TriggerOnObjectCreate AS t WHERE t.target_class IN ('$sClassList')- 遍历查询结果:
Trigger::DoActivate
DBObject::ActivateOnMentionTriggers- 遍历
iApplicationObjectExtension(在cmdbAbstractObject::DBInsert中)iApplicationObjectExtension::OnDBInsert
MetaModel::StopReentranceProtection(REENTRANCE_TYPE_UPDATE)(自 3.1.0 N°4756)- 如果对象被修改:
DBObject::DBUpdate(自 3.1.0 N°4756) finally:如果static::IsCrudStackEmpty()\cmdbAbstractObject::FireEventDbLinksChangedForAllObjects-EVENT_DB_LINKS_CHANGED(自 3.1.0 N°5906)
- 返回
DBObject::$m_iKey
DBUpdate(更新对象)
cmdbAbstractObject::DBUpdate- 如果没有更改则返回
DBObject::DBUpdateMetaModel::StartReentranceProtection(已在更新中则退出)(自 3.1.0 N°4756)DBObject::DoComputeValuescmdbAbstractObject::FireEventComputeValues-EventService::FireEvent(EVENT_DB_COMPUTE_VALUES)(自 3.1.0 N°4756)DBObject::ComputeValuesDBObject::GetState- 如果
$sState != '',遍历MetaModel::ListAttributeDefs- 如果
$oAttDef instanceof AttributeStopWatch:ormStopWatch::ComputeDeadlines
- 如果
DBObject::OnUpdatecmdbAbstractObject::FireEventBeforeWrite-EventService::FireEvent(EVENT_DB_BEFORE_WRITE, ['is_new' => false])(自 3.1.0 N°6324)DBObject::InitPreviousValuesForUpdatedAttributes(自 2.7.0 N°2293)- 将
$this->ListChanges()保存到$aChanges - 冻结更改
- 如果
count($this->ListChanges()) == 0MetaModel::StopReentranceProtection(REENTRANCE_TYPE_UPDATE)(自 3.1.0 N°4756)- 返回
DBObject::$m_iKey
DBObject::CheckToWrite- 如果
MetaModel::SkipCheckToWrite则返回 DBObject::SetReadOnly:从此处起不允许DBObject::Set(自 3.1.0 N°4756)cmdbAbstractObject::FireEventCheckToWrite-EventService::FireEvent(EVENT_DB_CHECK_TO_WRITE, ['is_new' => false])(自 3.1.0 N°4756)DBObject::SetReadWrite:从此处起允许DBObject::Set(自 3.1.0 N°4756)cmdbAbstractObject::DoCheckToWrite- 如果返回 false,则抛出
CoreCannotSaveObjectException - 保存原始值:
DBObject::$m_aOrigValues到$aOriginalValues变量 - 从
$aChanges中为\AttributeDefinition::IsBasedOnDBColumns == true的字段设置$aDBChanges CMDBSource::Query('START TRANSACTION')(自 2.7.0 N°679)- 如果
!MetaModel::DBIsReadOnly()- 更新每个层次键的左右索引
- 更新标量属性
- 使用当前类名和 id 创建新的
DBObjectSearch,并AllowAllData() DBObjectSearch::MakeUpdateQuery使用$aDBChanges\CMDBSource::Query执行更新查询
DBObject::DBWriteLinksDBObject::WriteExternalAttributes\AttributeCustomFields::WriteExternalValues
- 属性重置:
m_bDirty(设为 false),m_aTouchedAtt,m_aModifiedAtt=> 这导致ListChanges()返回空数组 DBObject::RecordAttChanges使用$aChangesCMDBSource::Query('COMMIT')(异常时 ROLLBACK)cmdbAbstractObject::PostUpdateActionsDBObject::PostUpdateActionscmdbAbstractObject::FireEventAfterWrite\cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification(自 3.1.0 N°5906)\cmdbAbstractObject::FireEventDbLinksChangedForCurrentObject-EVENT_DB_LINKS_CHANGED(自 3.1.0 N°5906)EventService::FireEvent(EVENT_DB_AFTER_WRITE, ['changes' => $aChanges, 'is_new' => false])(自 3.1.0 N°6324)DBObject::AfterUpdate(自 2.7.0 N°2293,更改可使用DBObject::ListPreviousValuesForUpdatedAttributes访问)
- 重置
DBObject::$m_aOrigValues TriggerOnObjectUpdate:遍历使用当前类或其父类的所有触发器TriggerOnObjectUpdate::DoActivate(自 3.0.0 N°3245 和 3.0.2 N°5389,TriggerOnObjectUpdate移至数据库更新之后)
- 重入调用(N°1073):
unset(DBObject.aUpdateReentrance[$sKey]) DBObject::ActivateOnMentionTriggers- 搜索
iApplicationObjectExtension实现iApplicationObjectExtension::OnDBUpdate(自 2.7.0 N°2293,更改可使用DBObject::ListPreviousValuesForUpdatedAttributes访问)
MetaModel::StopReentranceProtection()(自 3.1.0 N°4756)- 如果对象被修改且不是无限循环(自 3.1.0):
DBObject::DBUpdate(自 3.1.0 N°4756) - 返回
$this->m_iKey $this->SetWarningsAsSessionMessages('update')finally:如果static::IsCrudStackEmpty()\cmdbAbstractObject::FireEventDbLinksChangedForAllObjects-EVENT_DB_LINKS_CHANGED(自 3.1.0 N°5906)
- 返回
$res
DBDelete(删除对象)
cmdbAbstractObject::DBDeletecmdbAbstractObject::DBDeleteTracked_Internal- 搜索
iApplicationObjectExtension实现iApplicationObjectExtension::OnDBDelete
CMDBObject::DBDeleteTracked_InternalDBObject::DBDeleteDBObject::MakeDeletionPlanDeletionPlan::AddToDelete:将当前对象添加到待删除列表EventService::FireEvent(EVENT_DB_CHECK_TO_DELETE, ['deletion_plan' => $oDeletionPlan])(自 3.1.0 N°4756)cmdbAbstractObject::DoCheckToDeleteDBObject::DoCheckToDelete(@internal,但具有 DeletionPlan 参数)- 如果
$this->InSyncScope()则执行某些操作 iApplicationObjectExtension::OnCheckToDelete(可覆盖的钩子,但无法访问 DeletionPlan 实例)UserRights::IsActionAllowedDeletionPlan::SetDeletionIssuesDBObject::GetReferencingObjects- 遍历
$aDependentObjectsDeletionPlan::AddToUpdate:如果 ext key 有is_null_allowed=true参数DBObject::MakeDeletionPlan:否则
DeletionPlan::ComputeResults- 如果
$oDeletionPlan->FoundStopper():抛出DeleteException - 遍历
$oDeletionPlan->ListDeletes()DBObject::DBDeleteSingleObject
DBObject::SetReadOnly:从此处起不允许DBObject::Set(自 3.1.2 N°7118)EventService::FireEvent(EVENT_DB_ABOUT_TO_DELETE)(自 3.1.2 N°7118)DBObject::OnDelete$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL))SELECT TriggerOnObjectDelete AS t WHERE t.target_class IN (:class_list)- 遍历查询结果:
Trigger::DoActivate
- 遍历查询结果:
CMDBObject::RecordObjDeletion- 删除
CMDBChangeOp对象 DBObject::RecordObjDeletion\DBObject::RecordLinkSetListChange- 创建并持久化新的
CMDBChangeOpDelete
- 删除
- 遍历
MetaModel::ListAttributeDefs(get_class($this))- 如果
$oAttDef->IsHierarchicalKey():更新每个层次键的左右索引 - 否则如果
!$oAttDef->LoadFromDB():AttributeCustomFields::DeleteValue TemplateFieldsHandler::DeleteValues
- 如果
DBObject::DBDeleteCMDBSource::Query('START TRANSACTION')(自 2.7.0 N°679)- 遍历
MetaModel::EnumParentClasses(get_class($this), ENUM_PARENT_CLASSES_ALL)DBObject::DBDeleteSingleTable
CMDBSource::Query('COMMIT')(异常时 ROLLBACK)cmdbAbstractObject::FireEventAfterDelete\cmdbAbstractObject::NotifyAttachedObjectsOnLinkClassModification(自 3.1.0 N°5906)EventService::FireEvent(EVENT_DB_AFTER_DELETE)(自 3.1.0 N°6324)
DBObject::AfterDelete- 遍历
$oDeletionPlan->ListUpdates()DBObject::Set:重置 ext keyDBObject::DBUpdate
finally:如果static::IsCrudStackEmpty()\cmdbAbstractObject::FireEventDbLinksChangedForAllObjects-EVENT_DB_LINKS_CHANGED(自 3.1.0 N°5906)
ApplyStimulus(应用刺激)
没有重载,起始点在 DBObject 中。
DBObject::ApplyStimulusDBObject::EnumTransitions()EventService::FireEvent(EVENT_ENUM_TRANSITIONS)(自 3.1.2)- 如果刺激在当前状态无效果:返回 true
DBObject::Set:设置新状态- 遍历
$aTransitionDef['actions']- 如果
is_string($actionHandler):call_user_func($aActionCallSpec, $sStimulusCode)(pref 2.1.0 模块:直接调用方法) - 否则遍历
$aActionHandler['params']- 根据参数类型设置
$value $bRet = call_user_func_array($aCallSpec, $aParams)- 如果
$bRet === false:IssueLog::Info+$bSuccess = false
- 根据参数类型设置
- 如果
- 如果
$bSuccess- 秒表:启动或停止
- 如果
!$bDoNotWrite:DBObject::DBWrite- 如果
$this->m_bIsInDB:DBObject::DBUpdate - 否则:
DBObject::DBInsert
- 如果
- 搜索当前类及其父类的所有
TriggerOnStateLeaveTrigger::DoActivate
- 搜索当前类及其父类的所有
TriggerOnStateEnterTrigger::DoActivate
- 返回
$bSuccess
DoCheckToWrite
cmdbAbstractObject::DoCheckToWrite:警告不为空,覆盖时不要忘记调用父类!\DBObject::DoCheckToWriteDBObject::DoComputeValues- 设置未初始化的 “null-not-allowed” 日期时间(和日期)
DBObject::ComputeValuesDBObject::DoCheckUniqueness(参见专门章节)DBObject::ListChanges- 遍历
$aChangesDBObject::CheckValueDBObject::CheckConsistency
- 如果
DBObject::$m_bIsInDB && DBObject::InSyncScope && (count($aChanges) > 0)- 为每个因 datasynchro 锁定(
OPT_ATT_SLAVE)的属性在DBObject::$m_aCheckIssues中添加错误
- 为每个因 datasynchro 锁定(
- 遍历
iApplicationObjectExtensioniApplicationObjectExtension::OnCheckToWrite
- 如果
!$this->bAllowWriteUserRights::IsActionAllowedOnAttribute:检查每个更改是否允许(如果不允许,将错误添加到DBObject::$m_aCheckIssues)
原文:https://www.itophub.io/wiki/page?id=3_2_0:customization:sequence_crud
2025/01/13 13:29 by127.0.0.1
版本:3_2_0/customization/sequence_crud.txt · Last modified: 2025/01/13 13:29 by 127.0.0.1