Введение
ORM (Object-Relational Mapping) в 1С-Битрикс позволяет взаимодействовать с базой данных через объекты, упрощая разработку и делая код более читаемым. Одной из ключевых возможностей ORM является описание связей между сущностями. В этой статье мы разберем три типа отношений — oneToOne, oneToMany и manyToMany — и покажем их применение на практических примерах.
1. Отношение Reference (Один к одному / 1:1)
Что это?
Одна запись в таблице связана ровно с одной записью в другой таблице. Например, пользователь и его паспортные данные.
Реальный пример:
Представим интернет-магазин, где каждый пользователь (User) имеет единственный профиль доставки (DeliveryProfile).
Реализация в Битрикс ORM:
Сущность User:
namespace Local\ORM\Entity;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\Relations\Reference;
class UserTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName()
{
return 'b_user';
}
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
// Связь 1:1 с DeliveryProfile
(new Reference(
'DELIVERY_PROFILE', // Название связи
DeliveryProfileTable::class, // Целевая сущность
\Bitrix\Main\ORM\Query\Join::on('this.ID', 'ref.USER_ID') // Ссылка на поле в DeliveryProfileTable (USER_ID → UserTable.ID)
))
->configureJoinType('inner')
];
}
}
Сущность DeliveryProfile:
class DeliveryProfileTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName()
{
return 'delivery_profiles';
}
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
(new IntegerField('USER_ID')),
// Обратная связь
(new \Bitrix\Main\ORM\Fields\Relations\Reference(
'USER',
UserTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.USER_ID', 'ref.ID') // USER_ID в DeliveryProfileTable → ID в UserTable
))
];
}
}
Как использовать:
$user = UserTable::getById(1)->fetchObject();
$deliveryProfile = $user->get('DELIVERY_PROFILE'); // Получаем профиль доставки
2. Отношение oneToMany (Один ко многим / 1:N)
Что это?
Одна запись главной сущности связана с несколькими записями зависимой сущности. Например, блог и его посты.
Реальный пример:
Система блогов, где один блог (Blog) содержит множество статей (Article).
Реализация в Битрикс ORM:
Сущность Blog:
class BlogTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName()
{
return 'blogs';
}
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
(new StringField('NAME')),
// Связь oneToMany с Article
(new \Bitrix\Main\ORM\Fields\Relations\OneToMany(
'ARTICLES', // Название связи
ArticleTable::class, // Целевая сущность
'BLOG' // Ссылка на поле в ArticleTable (BLOG_ID → BlogTable.ID)
))
];
}
}
Сущность Article:
class ArticleTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
(new IntegerField('BLOG_ID')),
(new StringField('TITLE')),
// Связь с Blog
(new \Bitrix\Main\ORM\Fields\Relations\Reference(
'BLOG',
BlogTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.BLOG_ID', 'ref.ID') // BLOG_ID в ArticleTable → ID в BlogTable
))
];
}
}
Как использовать:
$blog = BlogTable::getById(1)->fetchObject();
$articles = $blog->get('ARTICLES'); // Все статьи блога
foreach ($articles as $article) {
echo $article->get('TITLE');
}
3. Отношение manyToMany (Многие ко многим)
Что это?
Записи одной сущности могут быть связаны с несколькими записями другой сущности через промежуточную таблицу. Например, студенты и курсы.
Реальный пример:
Учебная платформа, где студенты (Student) могут записываться на множество курсов (Course), а курс включает много студентов. Реализация в Битрикс ORM:
Промежуточная таблица StudentCourse:
class StudentCourseTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName()
{
return 'student_course';
}
public static function getMap()
{
return [
(new IntegerField('STUDENT_ID'))
->configurePrimary(),
(new IntegerField('COURSE_ID'))
->configurePrimary(),
// Связи с Student и Course
(new \Bitrix\Main\ORM\Fields\Relations\Reference(
'STUDENT',
StudentTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.STUDENT_ID', 'ref.ID')
)),
(new \Bitrix\Main\ORM\Fields\Relations\Reference(
'COURSE',
CourseTable::class,
\Bitrix\Main\ORM\Query\Join::on('this.COURSE_ID', 'ref.ID')
))
];
}
}
Сущности Student и Course:
class StudentTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
(new StringField('NAME')),
// Связь manyToMany через промежуточную таблицу
(new \Bitrix\Main\ORM\Fields\Relations\ManyToMany(
'COURSES', // Название связи
CourseTable::class, // Целевая сущность (курсы)
))
->configureTableName(StudentCourseTable::getTableName())
->configureLocalPrimary('ID', 'C_STUDENT_ID') //указывает, как будет называться привязка к полю из первичного ключа текущей сущности
->configureLocalReference('C_STUDENT') // зададим имя референса к текущей сущности
->configureRemotePrimary('ID', 'C_COURCE_ID') // указывает, как будет называться привязка к полю из первичного ключа сущности партнера
->configureRemoteReference('C_COURCE') // зададим имя референса к сущности партнера
];
}
}
class CourseTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getMap()
{
return [
(new IntegerField('ID'))
->configurePrimaryKey(),
(new StringField('NAME')),
// Связь manyToMany через промежуточную таблицу
(new \Bitrix\Main\ORM\Fields\Relations\ManyToMany(
'STUDENTS', // Название связи
StudentTable::class, // Целевая сущность (студенты)
))
->configureTableName(StudentCourseTable::getTableName())
->configureLocalPrimary('ID', 'C_COURCE_ID') //указывает, как будет называться привязка к полю из первичного ключа текущей сущности
->configureLocalReference('C_COURCE') // зададим имя референса к текущей сущности
->configureRemotePrimary('ID', 'C_STUDENT_ID') // указывает, как будет называться привязка к полю из первичного ключа сущности партнера
->configureRemoteReference('C_STUDENT') // зададим имя референса к сущности партнера
];
}
}
Как использовать:
$student = StudentTable::getById(1)->fetchObject();
$courses = $student->get('COURSES'); // Все курсы студента
foreach ($courses as $course) {
echo $course->get('NAME');
}
Советы и частые ошибки
- Индексы в промежуточных таблицах: Для manyToMany всегда добавляйте индексы на поля связи (например, STUDENT_ID и COURSE_ID), чтобы ускорить выборки.
- Каскадное удаление: Если запись главной сущности удаляется, определите поведение для зависимых данных. Например, в oneToMany можно использовать
->configureCascadeDeletePolicy(Bitrix\Main\ORM\Fields\Relations\CascadePolicy::FOLLOW). - Оптимизация запросов: Используйте
->addSelect('RELATION')при работе с getList(), чтобы избежать N+1 проблемы.
Заключение
Правильное использование отношений в Битрикс ORM делает код структурированным и эффективным. Реальные примеры, подобные описанным, помогут вам проектировать сложные системы с легкостью. Экспериментируйте, тестируйте и не забывайте документацию Битрикс!