按条件强制字段必填
本文档介绍如何在特定条件下强制字段必填。更多详细内容请参考 iTop 官方文档。
目标
此用例是强制提供字段的一种方式。
提交前检查
仅生产环境中的服务器
在此用例中,我们希望确保:
- 创建时,不提议位置
- 修改生产环境中的服务器时,位置变为必填
<class id="PhysicalDevice">
<fields>
<field id="location_id">
<!-- 如果状态更改,强制重新计算 location_id 标志 -->
<dependencies _delta="redefine">
<attribute id="org_id"/>
<attribute id="status"/>
</dependencies>
</field>
</fields>
</class>
<class id="Server" _delta="must_exist">
<event_listeners>
<event_listener id="evtSetInitialFlags" _delta="define">
<!-- 事件 ID 不需要与函数名相同,但也可以相同 -->
<event>EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS</event>
<rank>10</rank>
<!-- 回调必须是现有类方法的名称。名称自由 -->
<callback>evtSetInitialFlags</callback>
</event_listener>
<event_listener id="evtSetAttributeFlags" _delta="define">
<event>EVENT_DB_SET_ATTRIBUTES_FLAGS</event>
<rank>10</rank>
<callback>evtSetAttributeFlags</callback>
</event_listener>
</event_listeners>
<methods>
<method id="evtSetInitialFlags" _delta="define">
<static>false</static>
<access>public </access>
<comment>此方法在打开服务器创建表单之前调用一次</comment>
<code><![CDATA[
public function evtSetInitialAttributeFlags(Combodo\iTop\Service\Events\EventData $oEventData)
{ // 强制标志,忽略现有标志
$this->ForceInitialAttributeFlags('location_id', OPT_ATT_HIDDEN);
// $this->AddInitialAttributeFlags('location_id', OPT_ATT_HIDDEN); 如果其他代码也强制将其设为必填,可能不起作用
}
public function evtSetAttributeFlags(Combodo\iTop\Service\Events\EventData $oEventData)
{
if ((MetaModel::IsValidAttCode(get_class($this), 'status')) && ($this->Get('status') == 'production'))
{ // 添加必填标志
$this->AddAttributeFlags('location_id', OPT_ATT_MANDATORY);
// 可以决定设置此标志并忽略已为该属性设置的其他标志
// 在这种情况下,使用 ForceAttributeFlags 代替 AddAttributeFlags
$this->ForceAttributeFlags('location_id', OPT_ATT_MANDATORY);
}
}
仅生产环境中的服务器和网络设备
将上述事件和方法分别在 Server 和 NetworkDevice 类上声明两次。
仅生产环境中的数据中心设备
将上述事件和方法在 DatacenterDevice 类上声明,而不是 Server 类。
提交时检查
我们也可以在提交时检查是否提供了位置,如果没有,则阻止创建/修改并显示错误消息,以便用户填写位置后再次提交。
订阅 EVENT_DB_CHECK_TO_WRITE 事件,并定义对象类的回调方法 evtCheckToWrite():
- 此事件在写入数据库之前生成
- 如果遇到数据不一致,回调方法应提供错误消息。错误消息使用
$this->AddCheckIssue('Some Error Message')生成,警告消息使用$this->AddCheckWarning('Some Warning Message') - 从此方法返回时,如果至少有一个错误,对象不会写入数据库(创建或更新)
- 错误和警告消息仅在交互模式下显示给用户:控制台、门户、CSV 导入
- 对于数据同步、REST/JSON、CLI,根据跟踪级别记录在
itop/log/error.log中
迁移注意: 在设置上没有可见效果,但不符合规范的对象不能再被修改,直到它们变得合规。因此可能会阻止数据同步或 REST/JSON 脚本更新其他字段。要识别有问题的对象,请创建一个审计规则来检索不符合此新约束的对象,并在 UI 中或通过 CSV 导入逐一修复。
在 iTop 3.1.0 之前,可以使用扩展性 API,将相同代码放入 iApplicationObjectExtension::OnCheckToWrite() 中。
在此用例中,我们希望阻止服务器在未提供位置的情况下被设置为 “production” 状态。
<class id="Server" _delta="must_exist">
<event_listeners>
<event_listener id="evtCheckToWrite" _delta="define">
<event>EVENT_DB_CHECK_TO_WRITE</event>
<rank>10</rank>
<callback>evtCheckToWrite</callback>
</event_listener>
</event_listeners>
public function evtCheckToWrite(Combodo\iTop\Service\Events\EventData $oEventData)
{
// 防御性编程,确保 'status' 是当前类上的现有字段
// 然后检查条件:枚举值返回代码而非标签,因此我们测试代码
if (MetaModel::IsValidAttCode(get_class($this), 'status')
&& ($this->Get('status') == 'production'))
{
// AttributeExternalKey 永远不会为 NULL,0 是空值时使用的值
if (MetaModel::IsValidAttCode(get_class($this), 'location_id')
&& ($this->Get('location_id') == 0))
{
// 'Server:Error:LocationMandatoryInProduction' 必须声明为字典条目
$this->AddCheckIssue(Dict::Format('Server:Error:LocationMandatoryInProduction'));
}
}
}
也可以直接提供简单的纯文本错误消息:
$this->AddCheckIssue('Location is mandatory for all Servers in production');
在 XML 中定义字典条目的方式:
<entry id="Server:Error:LocationMandatoryInProduction" _delta="define">
<![CDATA['Location is mandatory for all Servers in production']]>
</entry>
原文:https://www.itophub.io/wiki/page?id=3_2_0:customization:mandatory-field-on-condition
版本:3_2_0/customization/mandatory-field-on-condition.txt · Last modified: 2025/05/21 10:58 by 127.0.0.1