В процессе разработки часто возникает задача получить не просто ссылку на объект (как внутренний идентификатор), а именно строковую навигационную ссылку вида e1cib/data/Справочник.Партнеры?ref=80da0cc47a6c412011e6d1853fb92181. Такая ссылка полезна для передачи во внешние системы, вставки в электронные письма или использования в интерфейсе для быстрого перехода к объекту.
Однако при попытке решить эту задачу "в лоб" с помощью написания запросов в 1С разработчики сталкиваются с рядом платформенных ограничений. В этой статье мы подробно разберем, почему это сложно сделать одним запросом, и рассмотрим эффективные способы обхода этих ограничений.
Проанализируем ситуацию, чтобы не допускать ошибок при вызове функций: навигационная ссылка состоит из текстового префикса, имени метаданных и уникального идентификатора (UUID). Казалось бы, достаточно просто "склеить" эти части. Но здесь нас поджидают три основные проблемы:
УникальныйИдентификатор(Ссылка). Но она возвращает значение специального типа УникальныйИдентификатор, а не строку. В языке запросов 1С нельзя принудительно привести UUID к строке, что подтверждает любой анализатор кода проектов (функция ВЫРАЗИТЬ не поддерживает тип СТРОКА для идентификаторов).550e8400-e29b-41d4-a716-446655440000), в то время как в навигационной ссылке после параметра ref= должен идти 32-символьный код без дефисов. В языке запросов нет функции СтрЗаменить(), поэтому часто используется вспомогательный код 1С для получения ссылки по GUID для очистки строки.Рассмотрим подробнее доступные решения этой задачи.
Если ваша задача связана с выводом данных в отчет или динамический список, Система компоновки данных (СКД) — это самый простой и правильный путь. В отличие от чистого запроса, СКД позволяет использовать функции встроенного языка в вычисляемых полях.
Разберем по шагам, как это настроить:
НавигационнаяСсылка.
ПолучитьНавигационнуюСсылку(Ссылка)
Платформа сама определит тип объекта и сформирует корректную ссылку для каждой строки результата. Это работает максимально эффективно, так как преобразование происходит на этапе формирования результата, а не в момент выполнения запроса к СУБД.
Для высоконагруженных систем, где ссылки нужно получать массово в сложных запросах или динамических списках без использования СКД, оптимальным решением будет материализация ссылки. Проанализируем этот подход: мы один раз вычисляем ссылку при записи объекта и сохраняем её в базе.
Для реализации этого метода выполним следующие действия:
Контрагенты) реквизит НавигационнаяСсылка с типом Строка (длина 100-150 символов).ПередЗаписью:
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Получаем ссылку. Для нового объекта сначала нужно получить ссылку.
Если ЭтоНовый() Тогда
УстановитьСсылкуНового(Справочники.Контрагенты.ПолучитьСсылку());
КонецЕсли;
НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(Ссылка);
КонецПроцедуры
Теперь в любом запросе мы можем просто обратиться к реквизиту НавигационнаяСсылка, что будет работать мгновенно:
ВЫБРАТЬ
Контрагенты.Наименование КАК Наименование,
Контрагенты.НавигационнаяСсылка КАК СсылкаТекстом
ИЗ
Справочник.Контрагенты КАК Контрагенты
Если нам нужно получить ссылку "здесь и сейчас" без изменения структуры метаданных, мы используем программную обработку результата запроса. Выясним, как это реализовать наиболее эффективно.
Рассмотрим пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Партнеры.Ссылка КАК Ссылка
|ИЗ
| Справочник.Партнеры КАК Партнеры";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Формируем ссылку на стороне сервера или клиента
ТекСсылка = ПолучитьНавигационнуюСсылку(Выборка.Ссылка);
// Далее используем полученную строку ТекСсылка
КонецЦикла;
Важный нюанс: Функция ПолучитьНавигационнуюСсылку() доступна на клиенте и на сервере. Если вы работаете с большим массивом данных, лучше делать это на сервере, чтобы избежать лишних сетевых вызовов.
Посмотрим на ситуацию с использованием новых возможностей платформы. По многочисленным просьбам разработчиков, в версию 8.3.22 была добавлена функция УникальныйИдентификатор(Ссылка) для языка запросов.
Пример использования в запросе:
ВЫБРАТЬ
УникальныйИдентификатор(Партнеры.Ссылка) КАК Идентификатор
ИЗ
Справочник.Партнеры КАК Партнеры
Хотя этот метод возвращает UUID, а не готовую навигационную ссылку, он позволяет выгрузить идентификаторы во временную таблицу, а затем при передаче данных на сторону встроенного языка (например, в ТаблицуЗначений), система автоматически сможет преобразовать их в строковое представление. Однако, как мы выяснили выше, собрать полную строку e1cib/... исключительно средствами SELECT в 1С всё еще невозможно из-за отсутствия функций конкатенации типов, отличных от строки, и отсутствия функций замены символов.
Проанализировав все способы, можно сделать следующие выводы:
ПолучитьНавигационнуюСсылку(Ссылка).ПриЗаписи.Помните, что формат ссылки ref=... чувствителен к порядку байтов. В СУБД (SQL Server/PostgreSQL) 1С хранит GUID в бинарном виде со смещением байтов. Поэтому попытки собрать ссылку прямым SQL-запросом к базе данных (через CAST к varchar) приведут к получению неверного идентификатора, который не будет распознан системой 1С как корректная ссылка.