# Симметричный линк между объектами одного типа

**URL:** <https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289>\
**Category:** Кастомизация\
**Created:** [26.Декабрь.2015 22:01:11 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289 "2015-12-26T22:01:11Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [26.Декабрь.2015 22:01:11 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/1 "2015-12-26T22:01:11Z")

</div>

Наткнулся на проблему и задумался над способом решения. Надо создать симметричный линк между объектами одного класса. Для объектов разного класса линк всегда симметричный. Поскольку выглядит например так **(id, server\_id, person\_id)** у соответствующих классов в соответствующем атрибуте будет **key\_to\_me=server\_id** у класса сервер и **key\_to\_me=person\_id** у персоны. Если в объекте класса сервер задать линк на персону то у персоны появится соответствующий линк на сервер.

Отлично. Но пусть теперь нам нужен линк Сервер-Сервер. Мы не можем создать линк-класс вида **(id,server\_id,server\_id)**, поля в базе не могут иметь одинаковые названия. Можем сделать только (id,left\_server\_id,right\_server\_id) но в классе сервер у нас соответствующий линку атрибут должен быть один, например, **key\_to\_me=left\_server\_id.**

Но тогда мы увидим линк только в том сервере на котором его задали, в “партнере” его не будет, поскольку его id записан в другом поле в left\_server\_id его нет.

Вот я и задумался, как эту проблему объехать. Один из способов оверлоадить в описании класса lnkServerToServer метод, который создает новый объект, чтобы прямо в нем создать еще одну симметричную запись в базе. Но засада в том, что на ITOP ни фига нет документации (или я не знаю, где ее найти).

Собственно вопрос:  
где найти описание? или может, кто знает, как решить эту проблему? Или сталкивался с аналогичным по сути случаем, когда надо было оверлоадить создание объекта. Откровенно говоря на вскидку по исходникам я не понял какая именно функция занимается созданием объекта. Я смотрел в cmdbAbstractClass но не понял. Если кто знает - ткните пальцем.  
Пока я вижу самым простым решением сделать внешнюю утилиту, которая будет проверять наличие симметричного линка и добавлять его в таблицу линк-класса, если он отсутствует. Это можно сделать через json. У них этот интерфейс хоть как-то описан.

И, пожалуйста, не пишите в стиле “зачем это нужно”, “да это и не нужно вовсе”. Это нужно. Излагать всю историю зачем и почему - утомлять читателей, которым и так понятно, и уходить от сути вопроса

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 17:14:23 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/2 "2015-12-27T17:14:23Z")

</div>

Ладно. я почти нашел.

```
<method id="DBInsert">

            <static>false</static>
            <access>public</access>
            <type>Overload-DBObject</type>
            <code><![CDATA[ public function DBInsert(){
                        $this->DBInsertNoReload(); 
                        $this->Reload();
                        $oMyClone = clone $this;
                       ......
                        $oMyClone->DBInsertNoReload();
                        $oMyClone->Reload(); 
                        return $this->m_iKey;
            } ]]></code>
        </method>

```

Вопрос остался с этим многоточием. Мне надо махнуть местами значения двух атрибутов в $oMyClone, Но я не понимаю сделать get и set для атрибута в объекте $oMyClone  
Должно быть что-то вроде $oMyClone-\>GetAttributeValue($AttCode) и $oMyClone-\>SetAttributeValue($AttCode, $value). Но как это правильно пишется?

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 18:09:10 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/3 "2015-12-27T18:09:10Z")

</div>

Ладно. Методои перебора вариантов установил:  
**$oMyClone-\>Get($AttName)**  
**$oMyClone-\>Set($AttName,$AttValue)**  
Всё отлично работает. Проблема решена.  
Хотелось бы конечно справочник по классам иметь ☹

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [27.Декабрь.2015 18:16:39 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/4 "2015-12-27T18:16:39Z")

</div>

На одну связь между двумя объектами два объекта-ссылки? Рационально.  
Об изменении/удалении подумали?

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 18:17:36 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/5 "2015-12-27T18:17:36Z")

</div>

Кстати, хорошо получилось. Даже в историю обоих связанных объектов пишется, что линк добавлен, когда и кем. Всё как положено. Правильную функцию оверлоадил.

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 18:27:24 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/6 "2015-12-27T18:27:24Z")

</div>

Очень даже рационально. Именно так сделано в Altiris CMDB, которая сейчас Symantec. Удаление также можно оверлоадом сделать.  
А вот то, что свойство ссылки “направленная” или “симметричная” фактически определяется классами линкуемых объектов, это полный пипец. У нормальных людей просто два типа ссылок определяются и можно явно указать какая ссылка. Но как говорится "дареному коню …"  
И да симметричная ссылка реализуется двумя строками в таблице. Так, что велосипед изобретать не надо.  
Кстати надо теперь delete оверлоадить. Щас сделаю.

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [27.Декабрь.2015 18:28:29 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/7 "2015-12-27T18:28:29Z")

</div>

[http://www.combodo.com/documentation/api-ref-extensions/classes/iApplicationObjectExtension.html](http://www.combodo.com/documentation/api-ref-extensions/classes/iApplicationObjectExtension.html)

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [27.Декабрь.2015 18:41:46 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/8 "2015-12-27T18:41:46Z")

</div>

> [@esguardian](#):
>
> Очень даже рационально.

Сложно говорить аргументированно, не зная конечно цели этой задачи.

> [@esguardian](#):
>
> Но тогда мы увидим линк только в том сервере на котором его задали, в “партнере” его не будет, поскольку его id записан в другом поле в left\_server\_id его нет.

Если проблема только в выводе, не проще ли этот самый вывод и подправить?

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 19:02:27 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/9 "2015-12-27T19:02:27Z")

</div>

Я думаю не проще. Там ведь не только вывод. Там еще связанные операции с элементами списка. Всякие добавить/удалить. Я думал оставить одну строку на линк и поправить презентацию. Но потом решил не изобретать велосипед и сделать как в других системах, две строки на симметричный линк.  
Мне нужно задавать пары несовместимых объектов. Это симметричное отношение. Речь идет об управлении бизнес-ролями. Есть такая штука - несовместимые роли, ну типа исполнитель-контролер. Собственно модуль я уже написал. Нормально всё работает. И в процессах управления изменениями всё вставилось. Я их с тикетами тоже связал.  
Вот мелочи сейчас приделываю. А вопросы такие детские, так я просто этот itop неделю назад увидел первый раз. Подумал, вроде подходящая система. Вот только с докой тихий ужас. Учитывая. что я PHP вообще не знаю по коду тяжеловато разбираться. Если бы хоть знать где искать нужные куски кода 🙂

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [27.Декабрь.2015 19:32:39 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/10 "2015-12-27T19:32:39Z")

</div>

Да, там не только вывод. Потому и спрашиваю. Как я понял, линк Сервер-Сервер приведен просто в кач-ве примера. У айтопа есть логика оценки влияние КЕ друг на друга, которая использует линки. Будьте внимательны, если будете связывать таким образом две функциональные КЕ.  
На счет доков - хз, вроде на уровне XML модели данных всё ок. Для более глубокой модификации есть интерфейсы [https://wiki.openitop.org/doku.php?id=2\_2\_0:customization:extensions\_api](https://wiki.openitop.org/doku.php?id=2_2_0:customization:extensions_api). Можно и вывод ими поправить, и логику. Я бы вместо оверлода использовал их. Ну и вопросы это далеко не детские.

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [27.Декабрь.2015 19:46:57 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/11 "2015-12-27T19:46:57Z")

</div>

Я специально стандартный FunctionalCI не наследовал. Сделал свой верхнего уровня абстрактный SecurityRole и из него два реальных BusinessRole и ApplicationRole первый для документирования ролей привязанных к Бизнес-процессам второй к Прикладным решениям. К другим типам КЕ роли вязать смысла нет.  
В моем случае без оверлоада никак не обойтись. Да и не очень это страшно. Он как я посмотрел повсюду используется. В тех же КЕ закладка со списком активных тикетов оверлоадом делается. Я для ролей такую же сделал. Очень удобно.  
А как линки уничтожать я уже схематично разобрался. Можно использовать new DBObjectSet (DBSearch::OQLQwery…) где выбрать по значению атрибутов у this и их симметричному значению. А потом foreach in DBOdjectSet сделать DBSingleObjectDelete. Не сложно.

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [28.Декабрь.2015 13:37:36 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/12 "2015-12-28T13:37:36Z")

</div>

Так и сделалось в итоге. Вписал оверлоад метода DBObject-\>AfterDelete(). Получилось чистенько. И линки парные удаляются и в историю изменений линкованых объектов делается запись об удалении также симметрично.  
Не пойму как в здешнем интерфейсе код вписать. Если кому интересно, в качестве сниппета он лежит здесь [https://bitbucket.org/snippets/esguardian/585qX](https://bitbucket.org/snippets/esguardian/585qX)  
Весь модуль в репозитарии вечерком обновлю.

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [28.Декабрь.2015 14:59:58 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/13 "2015-12-28T14:59:58Z")

</div>

> [@esguardian](#):
>
> Не пойму как в здешнем интерфейсе код вписать

как-то так:

````auto
class BidirectionalLinkExtension implements iApplicationObjectExtension
{
   public static function OnDBInsert($oObject, $oChange)
   {
      if ($oObject instanceof lnkSecurityRoleBidirectional)
      {
        $oMyClone = clone $oObject;
        $oMyClone->Set('left_securityrole_id',$oObject->Get('right_securityrole_id'));
        $oMyClone->Set('right_securityrole_id',$oObject->Get('left_securityrole_id'));
        $oMyClone->DBInsertNoReload();
      }
   }
   ...
}
```
````

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [28.Декабрь.2015 18:30:29 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/14 "2015-12-28T18:30:29Z")

</div>

Красиво.  
А я когда выбираю в меню тег pre code и вставляю код, в окошке предпросмотра получается какая-то ерунда. Половина тегов не рисуется. Надо разобраться.

А про пользование IApplicationObjectExtension он у меня подозрение вызвал из-за расхождения доки с тем, что я увидел в коде класса DBObject. Вот в DBObject есть пустой метод AfterDelete(), специально для оверлоада оставлен и он вызывается из DBSingleObgectDelete() в самом конце. А в доке на IApplicationObjectExtension такого метода нет. То ли дока неверна, то ли интерфейс и правда его не содержит.

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [28.Декабрь.2015 19:12:44 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/15 "2015-12-28T19:12:44Z")

</div>

> [@esguardian](#):
>
> А я когда выбираю в меню тег pre code и вставляю код, в окошке предпросмотра получается какая-то ерунда. Половина тегов не рисуется. Надо разобраться.

Нужно строкой выше и строкой ниже кода вставить ``` (три косых апострофа) или четыре пробела перед каждой строкой.

В `IApplicationObjectExtension` есть метод `OnDBDelete()`, дёргается в cmdbAbstractObject перед удалением объекта из базы. Не спорю, можно и в DBObject методы оверлодить. Просто это более “глубокий” уровень, и вопрос в том, насколько сильно вы хотите потом поддерживать ваши доработки. Интерфейсы всё таки описаны разработчиками и точно будут совместимы с последующими версиями. В общем, тут хозяин – барин.

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [28.Декабрь.2015 19:23:03 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/16 "2015-12-28T19:23:03Z")

</div>

Спасибо. Понял.  
С OnDBDelete() проблема как раз в том, что он вызывается перед удалением, а не после. А по поводу интерфейсов согласен. Обычно они более “стабильны”.

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [30.Декабрь.2015 13:58:14 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/17 "2015-12-30T13:58:14Z")

</div>

Всё. Тему можно закрыть. Если кому интересен конкретный код, он здесь [https://bitbucket.org/esguardian/itop-extensions](https://bitbucket.org/esguardian/itop-extensions)  
Кстати, я не профессиональный разработчик. Если есть советы по улучшению кода и “чистописанию”, приму с благодарностью.

---

<div class="post-metadata">

**Author:** ![vladimir](https://community.itop-itsm.ru/user_avatar/community.itop-itsm.ru/vladimir/32/687_2.png) [@vladimir](https://community.itop-itsm.ru/u/vladimir)\
**Post date:** [30.Декабрь.2015 14:47:39 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/18 "2015-12-30T14:47:39Z")

</div>

Если есть желание, можете создать тему в разделе [Модули](https://community.itop-itsm.ru/c/kastomizacziya/moduli).

Прочитал описание, пробежал глазами код, но так и не смог понять, может ли мне быть полезен это модуль. Может это потому что я далёк от информационной безопасности? Можете рассказать более подробно о его предназначении? Если я правильно понял, к ролям пользователей в iTop он отношение не имеет, а добавляет новые КЕ из области ИБ?

---

<div class="post-metadata">

**Author:** ![esguardian](https://community.itop-itsm.ru/letter_avatar_proxy/v4/letter/e/c0e974/32.png) [@esguardian](https://community.itop-itsm.ru/u/esguardian)\
**Post date:** [30.Декабрь.2015 15:03:38 UTC](https://community.itop-itsm.ru/t/simmetrichnyj-link-mezhdu-obektami-odnogo-tipa/289/19 "2015-12-30T15:03:38Z")

</div>

Ага. Так и есть.

У нас есть целая проблема управления ролями пользователей как в бизнес-процессах, так и в отдельных прикладных системах. Например, в автоматизированной банковской системе. По стандартам ЦБ управление доступом должно быть построено на основе ролевой модели. Собственно для описания этой модели нужны какие-то удобные средства. Обычно это делается в каких-нибудь файлах Excel и ужасно сложно контролировать связи и изменения назначений ролей. Без CMDB это всё расползается в полный бардак.  
Кроме того есть проблема конфликтных ролей. Например в платежных процессах нельзя совмещать в одном лице подготовку платежного документа, его контроль и само осуществление платежа. В идеале это три разные роли. Конфликтность назначенных человеку ролей тоже надо проверять.

В CMDB вести учет гораздо проще, но коммерческие системы очень дорого стоят. Мне сейчас как раз нужно средство учета, поскольку у меня тут накопился очень серьезный беспорядок. iTop мне понравился. Хорошая вещь. Как раз подойдет.
