×

扫描二维码登录本站

QQ登录

只需一步,快速开始

二次开发- 修改界面-字段约束条件

标签: 暂无标签
本帖最后由 adminlily 于 2020-12-16 09:41 编辑

字段约束条件
先决条件:您必须熟悉教程中使用的语法 并且已经创建了一个扩展.

学习:施加数据完整性规则

水平:

域:PHP, Constrain

最低版本:2.1.0

在下面的示例中,我们将使用一种方法来检测不一致性并防止将此类对象保存在数据库中。

  • 控制台或门户中的此方法在提交后报告错误。
  • 并防止创建和更新由DataSynchro,REST/JSON和CSV导入完成的含混的对象。



理论

我们将覆盖对象类的方法DoCheckToWrite():

  • 即将在写入数据库之前调用此方法-请参见调用堆栈.
  • 如果该方法遇到数据不一致性,则应提供错误消息。
  • 错误消息记录在数组$ this-> m_aCheckIssues []中,
  • 警告消息记录在数组$ this-> m_aCheckWarnings []中,
  • 从该方法返回时,如果至少有一个错误,则不会将对象写入数据库(创建或更新)
  • 错误和警告消息是
    • 仅以交互模式显示到用户:控制台,门户,CSV导入
    • 在跟踪DataSynchro,REST/JSON,CLI的级别上登录itop/plog/error.log依赖



- - 被检查 !-

迁移:对设置没有可见的影响,但是在符合标准之前,不能再修改不符合标准的对象。因此,这可能会阻止datasynchro或REST/JSON脚本更新其他字段,例如。

要识别故障对象,请创建审计规则以检索不符合此新约束的对象,并在UI或CSV导入中一一修复它们。

DoCheckToWrite方法可以在所有情况下防止创建或修改:在控制台,门户,CSV导入,DataSynchro和REST/JSON API中
除了覆盖DoCheckToWrite()方法,您还可以使用扩展API 并将相同的代码放入iApplicationObjectExtension :: OnCheckToWrite()

  • 该API的优势在于,多个扩展可以并行进行检查,
  • 方法的覆盖只能由一个扩展名完成。



例子
开始日期<结束日期

在此用例中,我们将防止记录变更的结束日期早于开始日期。


public function DoCheckToWrite()
   {
      // Always ask the parent class to perform its own check
      parent::DoCheckToWrite();
      // Defensive programming, ensuring that 'end_date' and 'start_date' has not

been removed
      // from the Change class by some extensions which I am not yet aware of.
      // Get the value in seconds before comparing them is safer
      if (MetaModel::IsValidAttCode(($this), 'start_date')
       && MetaModel::IsValidAttCode(($this), 'end_date')
       && (AttributeDateTime::GetAsUnixSeconds($this->Get('start_date'))
         > AttributeDateTime::GetAsUnixSeconds($this->Get('end_date'))))
      {
         $this->m_aCheckIssues[] = Dict::Format

('Class:Error:EndDateMustBeGreaterThanStartDate');
      }
   }

生产服务器所需的位置
在此用例中,我们要防止将服务器放入“生产”状况中,而无需提供位置。


public function DoCheckToWrite()
{
   // Always ask the parent class to perform their own check
   parent::DoCheckToWrite();
   // Defensive programming, ensuring that 'status' is an existing field on the

current class
   // then checking the condition: an enum value returns code, not label, so we

test the code,
   if (MetaModel::IsValidAttCode(($this), 'status')
   && ($this->Get('status') == 'production'))
   {
      // AttributeExternalKey are never NULL, O is the value used when empty
      if (MetaModel::IsValidAttCode(($this), 'location_id')
      && ($this->Get('location_id') == 0))
      {
         // 'Server:Error:LocationMandatoryInProduction' must be declared as a

dictionary entry
         $this->m_aCheckIssues[] = Dict::Format

('Server:Error:LocationMandatoryInProduction');
      }
   }
}

// You may also provide a simple error message in plain text $this->m_aCheckI

这是在XML中定义字典条目的方法:


    <entry id="Server:Error:LocationMandatoryInProduction" _delta="define">
      <![CDATA['Location is mandatory for all Servers in production']]>
    </entry>

FunctionalCI名称唯一

在此用例中,我们要防止两个FunctionalCI具有相同的名称。除非FunctionalCI实际上是SoftwareInstance,
MiddlewareInstance,DatabaseSchema或ApplicationSolution,在这种情况下,我们不在乎。

唯一性规则 可以执行类似的唯一性检查,但全部以XML进行,而无需编写PHP代码。


public function DoCheckToWrite()
{
    // Call the function on the parent class as it may need to check stuff as well
    parent::DoCheckToWrite();
    // Check that the name of the FunctionalCI must be unique
    $aChanges = $this->ListChanges();
    // Check if the name field was set or changed
    if (('name', $aChanges))
    {
      $sNewName = $aChanges['name'];
      // Retrieve all FunctionalCI having that new name, ignoring CIs from some

sub-classes
      $oSearch = DBObjectSearch::FromOQL_AllData("
         SELECT FunctionalCI WHERE name = :newFCI
         AND finalclass NOT IN

('DBServer','Middleware','OtherSoftware','WebServer',
            

'PCSoftware','MiddlewareInstance','DatabaseSchema','ApplicationSolution')
      ");
      $oSet = new DBObjectSet($oSearch, (), ('newFCI' => $sNewName));
      // If there is at least one FunctionalCI matching the required name
      if ($oSet->() > 0)
      {
         // Block the FunctionalCI writing the Database
         $this->m_aCheckIssues[] = Dict::Format

('Class:FunctionalCI:FCINameMustBeUnique', $sNewName);
      }
   }
}

用户必须具有简档
这就是iTop如何确保用户始终至少连接一个简档的方式。

  • 强制n:n关系至少具有一个条目是一个很好的例子。
  • 请注意,这还不足以防止删除简档,而这将是给定用户中的唯一一个
    • 在此特定示例中没什么大不了的,因为iTop UI并不意味着删除简档就是供应


如果对当前对象的其他对象进行检查,则DoCheckToWrite或iApplicationObjectExtension :: OnCheckToWrite()无法保证将始终应用该规则。例如是这种情况。在本示例中,在LinkedSet或LinkedSetIndirect字段上测试条件时。

写一个关于如何确保LinkedSet字段总是至少一个条目的教程


public function DoCheckToWrite()
{
    // Call the function on the parent class as it may need to check stuff as well
    parent::DoCheckToWrite();
    // Check that the name of the FunctionalCI must be unique
    $aChanges = $this->ListChanges();
   // Check if the profile list was changed to avoid loading it for nothing
   if (('profile_list', $aChanges))
   {
        $oSet = $this->Get('profile_list');
        if ($oSet->() == 0)
        {
             $this->m_aCheckIssues[] = Dict::S

('Class:User/Error:AtLeastOneProfileIsNeeded');
        }
    }
}






上一篇:二次开发- 修改界面-字段值预选
下一篇:二次开发- 修改界面-创建新类型仪表板
manm

写了 277 篇文章,拥有财富 1480,被 3 人关注

您需要登录后才可以回帖 登录 | 立即注册
B Color Link Quote Code Smilies

成为第一个吐槽的人

手机版|小黑屋|最新100贴|论坛版块|ITIL先锋论坛 |粤ICP备11099876号|网站地图
Powered by Discuz! X3.4 Licensed  © 2001-2017 Comsenz Inc.
返回顶部