Работа с метаданными

Метаданные удаленной конфигурации представляют собой дерево объектов, описывающих состав и свойства следующих объектов системы:

  • коллекций объектов конфигурации;
  • объектов конфигурации (справочников, документов и пр..);
  • реквизитов и табличных частей объектов.

Прямой доступ к метаданным

Дерево метаданных доступно в свойстве "Метаданные" объекта "БромКлиент". Через данное свойство может быть получен доступ ко всем подчиненным узлам на требуемой глубине:

// Получаем узел коллекции справочников
$узелСпискаСправочников = $клиент->Метаданные->Справочники;

// Выводим список справочников на экран
foreach ($узелСпискаСправочников as $имя => $узел) {
	echo($узел->Имя() . "<br/>");
}
// Получаем узел коллекции реквизитов справочника "Номенклатура"
$узелСпискаРеквизитов = $клиент->Метаданные->Справочники->Номенклатура->Реквизиты;

// Выводим список реквизитов на экран
foreach ($узелСпискаРеквизитов as $имя => $узел) {
	echo($узел->Имя() . "<br />");
}
// Получаем узел коллекции общих модулей
$узелСпискаОбщихМодулей = $клиент->Метаданные->ОбщиеМодули;

// Выводим список общих модулей
foreach ($узелСпискаОбщихМодулей as $имя => $узел) {
	echo($узел->Имя() . "<br />");
}
// Получаем узел коллекции общих модулей
$узелДокумента = $клиент->Метаданные->Документы->ЗаказКлиента;

// Выводим список общих модулей
foreach ($узелДокумента as $имя => $узел) {
	echo($узел->Синоним() . "<br />");
}

Доступ к подчиненному узлу метаданных на требуемой глубине может быть получен также вызовом методов "Найти()" или "ПопыткаНайти()":

// Получаем узел коллекции реквизитов справочника "Номенклатура"
$узелСпискаРеквизитов1 = $клиент->Метаданные->Найти("Справочники.Номенклатура.Реквизиты");

// или то же самое
$узелСпискаРеквизитов2 = $клиент->Метаданные->Найти("Справочники")->Найти("Номенклатура.Реквизиты");

// или то же самое
$узелСпискаРеквизитов3 = $клиент->Метаданные->Найти("Справочники")->Найти("Номенклатура")->Найти("Реквизиты");
// Получаем реквизиты табличной части "Товары" документа "ЗаказКлиента"
$узелСпискаРеквизитов = $клиент->Метаданные->Найти("Документы.ЗаказКлиента.ТабличныеЧасти.Товары.Реквизиты");
$узел = null;
if ($клиент->Метаданные->ПопыткаНайти("Документы.ЗаказКлиента.ТабличныеЧасти.Товары", $узел)) {
	echo($узел->Синоним());
}

Косвенный доступ к метаданным

Обращение к узлам метаданных конфигурации происходит автоматически в следующих случаях:

  • при создании/получении ссылок на объекты;
  • при обращении к контекстным данным ссылок (к реквизитам и табличным частям);
  • при обращении к контекстным данным объектов (к реквизитам и табличным частям);
  • при обращении к общим модулям и модулям менеджеров объектов.

Обращение к узлам метаданных происходит для контроля наличия тех или иных объектов конфигурации, а также для определения их полного состава.

$текСсылка = $клиент->Справочники->Номенклатура->НайтиПоНаименованию("Телевизор");

// Происходит автоматическое обращение к узлам "Справочники" и "Справочники.Номенклатура"
// для проверки их существования в данной конфигурации.
$текСсылка = $клиент->Перечисления->СтавкиНДС->НДС18;

// Происходит автоматическое обращение к узлам "Перечисления" и "Перечисления.СтавкиНДС"
// для проверки их существования в данной конфигурации, а также для получения
// предопределенного значения "НДС18".
$результат = $клиент->РаботаСДанными->ПолучитьДанные();

// Происходит автоматическое обращение к узлам "ОбщиеМодули" и "ОбщиеМодули.РаботаСДанными"
// для проверки их существования в данной конфигурации.

Загрузка метаданных

При прямом или косвенном обращении к объектам метаданных происходит их автоматическая загрузка с сервера. По этой причине первое обращение к объектам определенного типа сопровождается дополнительными серверными вызовами. Чтобы уменьшить количество таких вызовов, можно заранее загрузить метаданные одним или несколькими запросами.

Для загрузки метаданных необходимо вызвать метод "ЗагрузитьМетаданные()" объекта "БромКлиент" и указать первым параметром список объектов, которые должны быть загружены. Если требуемых объектов много, то лучше проводить загруку несколькими пакетами. В качестве второго опционального параметра метода можно указать максимальное количество объектов в одном пакете. Клиентский модуль самостоятельно загрузит метаданные с учетом указанных ограничений.

// Загружаем все объекты метаданных единым блоком (не рекомендуется)   
$клиент->ЗагрузитьМетаданные("*");
// Загружаем все объекты метаданных пакетами по 100 объектов 
$клиент->ЗагрузитьМетаданные("*", 100);
// Загружаем только некоторые коллеции метаданных пакетами по 100 объектов
$клиент->ЗагрузитьМетаданные("Справочники.*, Документы.*", 100);

// или сокращенно
$клиент->ЗагрузитьМетаданные("Справочники, Документы", 100);
// Загружаем только конкретные объекты метаданных
$клиент->ЗагрузитьМетаданные("Справочники.Номенклатура, Справочники.Контрагенты, Документы.ЗаказКлиента");

ВАЖНО!
Метаданные сложных промышленных конфигураций могут содержать десятки и даже сотни мегабайт данных. По этой причине их передача одним пакетом может занимать длительное время и приводить к возникновению ошибок передачи данных: к превышению допустимого размера сообщений или к превышению времени обработки запросов. При необходимости загрузки полного дерева метаданных рекомендуется проводить такую загрузку пакетами ограниченного размера, например по 100-250 объектов в пакете.

Кеширование метаданных

Чтобы не загружать метаданные с сервера при каждом запуске приложения, в библиотеке реализованы механизмы кеширования метаданных на стороне клиента. Для использования данного механизма достаточно создать объект, управляющий кешем, и передать его клиенту:

// Кешируем метаданнные в файловой системе (требуются права на чтение и запись)
$клиент->Метаданные->Кеш = new ФайловыйКешМетаданных("Temp/Cache");
// Кешируем метаданнные в файловой системе (требуются права на чтение и запись)
$клиент->Метаданные->Кеш = new ФайловыйКешМетаданных("Temp/Cache");

// Если необходимо очистить кеш
$клиент->Метаданные->Кеш->Очистить();

В библиотеке реализован простейший кеш с использованием файловой системы. Чтобы реализовать кеш с использованием других механизмов (например, с использованием базы данных), достаточно создать собественный класс кеша, реализующий интерфейс "ИКешМетаданных".

ВАЖНО!
Метод ЗагрузитьМетаданные() всегда загружает данные непосредственно с сервера, игнорируя кеш. При этом загруженные данные кешируются, если менеджер кеша был установлен.