n:n 自反与对称关系
n:n 自反与对称关系。
本文档介绍如何创建类与自身的对称多对多关系。更多详细内容请参考 iTop 官方文档。
概述
创建类与自身的对称关系,例如人员的同事关系。若 John 是 Anna 的同事,则 Anna 也是 John 的同事。
iTop 默认的多对多关系不是对称的。本教程通过自动创建双向记录来实现对称性。
人员同事关系
核心思路
当用户创建 (src_person = John, dest_person = Anna) 时,后台自动创建其镜像 (src_person = Anna, dest_person = John)。
AfterInsert
public function AfterInsert()
{
$oSearch = DBSearch::FromOQL('SELECT lnkPersonToPerson WHERE src_person_id = :src_id AND dest_person_id = :dest_id');
$oSet = new DBObjectSet($oSearch, array(),
array(
'src_id' => $this->Get('dest_person_id'),
'dest_id' => $this->Get('src_person_id'),
),
);
if ($oSet->Count() == 0) {
$oLnk = MetaModel::NewObject("lnkPersonToPerson",
array('src_person_id' => $this->Get('dest_person_id'),
'dest_person_id' => $this->Get('src_person_id')));
$oLnk->DBInsert();
}
}
AfterUpdate
public function AfterUpdate()
{
$aChanges = $this->ListPreviousValuesForUpdatedAttributes();
$sPrevSrc = array_key_exists('src_person_id', $aChanges) ? $aChanges['src_person_id'] : $this->Get('src_person_id');
$sPrevDest = array_key_exists('dest_person_id', $aChanges) ? $aChanges['dest_person_id'] : $this->Get('dest_person_id');
$oSearch = DBSearch::FromOQL('SELECT lnkPersonToPerson WHERE src_person_id = :src_id AND dest_person_id = :dest_id');
$oSet = new DBObjectSet($oSearch, array(),
array(
'src_id' => $sPrevDest,
'dest_id' => $sPrevSrc,
),
);
if ($oSet->Count() > 0) {
while($oLnk = $oSet->Fetch()) {
$oLnk->Set('src_person_id', $this->Get('dest_person_id'));
$oLnk->Set('dest_person_id', $this->Get('src_person_id'));
$oLnk->DBUpdate();
}
} else {
$oSearchNew = DBSearch::FromOQL('SELECT lnkPersonToPerson WHERE src_person_id = :src_id AND dest_person_id = :dest_id');
$oSetNew = new DBObjectSet($oSearchNew, array(),
array(
'src_id' => $this->Get('dest_person_id'),
'dest_id' => $this->Get('src_person_id'),
),
);
if ($oSetNew->Count() === 0) {
$oLnk = MetaModel::NewObject("lnkPersonToPerson", array(
'src_person_id' => $this->Get('dest_person_id'),
'dest_person_id' => $this->Get('src_person_id'),
));
$oLnk->DBInsert();
}
}
}
AfterDelete
public function AfterDelete()
{
$oSearch = DBSearch::FromOQL('SELECT lnkPersonToPerson WHERE src_person_id = :src_id AND dest_person_id = :dest_id');
$oSet = new DBObjectSet($oSearch, array(),
array(
'src_id' => $this->Get('dest_person_id'),
'dest_id' => $this->Get('src_person_id'),
),
);
if ($oSet->Count() > 0) {
while($oLnk = $oSet->Fetch()) {
$oLnk->DBDelete();
}
}
}
NetworkDevice & ConnectableCI
此用例来自 iTop 默认数据模型,比上面的更复杂,因为有时对称有时不对称,取决于 ConnectableCI 是否也是 NetworkDevice。
AfterInsert
public function AfterInsert()
{
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice')) {
$sOQL = "SELECT lnkConnectableCIToNetworkDevice
WHERE connectableci_id = :device AND networkdevice_id = :network
AND network_port = :nwport AND device_port = :devport";
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'network' => $this->Get('connectableci_id'),
'device' => $this->Get('networkdevice_id'),
'devport' => $this->Get('network_port'),
'nwport' => $this->Get('device_port'),
)
);
if ($oConnectionSet->Count() == 0) {
$sLink = $this->Get('connection_type');
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
$oNewLink = new lnkConnectableCIToNetworkDevice();
$oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
$oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
$oNewLink->Set('network_port', $this->Get('device_port'));
$oNewLink->Set('device_port', $this->Get('network_port'));
$oNewLink->Set('connection_type', $sConnLink);
$oNewLink->DBInsert();
}
}
}
AfterDelete
public function AfterDelete()
{
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false);
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice')) {
$sOQL = "SELECT lnkConnectableCIToNetworkDevice
WHERE connectableci_id = :device AND networkdevice_id = :network
AND network_port = :nwport AND device_port = :devport";
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
array(),
array(
'network' => $this->Get('connectableci_id'),
'device' => $this->Get('networkdevice_id'),
'devport' => $this->Get('network_port'),
'nwport' => $this->Get('device_port'),
)
);
while ($oConnection = $oConnectionSet->Fetch()) {
$oConnection->DBDelete();
}
}
}
原文:https://www.itophub.io/wiki/page?id=3_2_0:customization:n-n-reflexive-relation
版本:3_2_0/customization/n-n-reflexive-relation.txt · Last modified: 2024/09/10 10:25 by 127.0.0.1