Использовать Bitrix ORM не сложно. Работа ведется с таблицами, а не сущностями (как в старом ядре). Список таблиц БД Bitrix можно увидеть по ссылке
Как использовать ORM
Вначале нужно подключить модуль, с которым будет вестись работа. Например:
\Bitrix\Main\Loader::includeModule('iblock');Пример запроса в таблицу , содержащую элементы инфоблока:
$dbItems = \Bitrix\Iblock\ElementTable::getList([
'order' => ['SORT' => 'ASC'], // сортировка
'select' => ['ID', 'NAME', 'IBLOCK_ID', 'SORT', 'TAGS'], // выбираемые поля, без свойств. Свойства можно получать на старом ядре \CIBlockElement::getProperty
'filter' => ['IBLOCK_ID' => 4,
'LOGIC' => 'OR',
[
'ID' => 41,
],
[
'ID' => 42, // Второе условие для "или"
],
], // фильтр только по полям элемента, свойства (PROPERTY) использовать нельзя
'group' => ['TAGS'], // группировка по полю, order должен быть пустой
'limit' => 1000, // целое число, ограничение выбираемого кол-ва
'offset' => 0, // целое число, указывающее номер первого столбца в результате
'count_total' => 1, // дает возможность получить кол-во элементов через метод getCount()
'runtime' => array(), // массив полей сущности, создающихся динамически
'data_doubling' => false, // разрешает получение нескольких одинаковых записей
'cache' => [ // Кеш запроса. Сброс можно сделать методом \Bitrix\Iblock\ElementTable::getEntity()->cleanCache();
'ttl' => 3600, // Время жизни кеша
'cache_joins' => true // Кешировать ли выборки с JOIN
],
]);Что можно делать с $dbItems?
$dbItems->fetch(); // или $dbItems->fetchRaw() получение одной записи, можно перебрать в цикле while ($arItem = $dbItems->fetch())
$dbItems->fetchAll(); // получение всех записей
$dbItems->fetchCollection(); // получение всех записей в виде объектов (коллекций)
$dbItems->getCount(); // кол-во найденных записей без учета limit, доступно если при запросе было указано count_total = 1
$dbItems->getSelectedRowsCount(); // кол-во полученных записей с учетом limitДругие методы:
checkFields(Result $result, $primary, array $data) // метод проверяет поля данных перед записью в БД.
getById($id) // получение элемента по ID
getByPrimary($primary, array $parameters = array()) // метод возвращает выборку по первичному ключу сущности и по опциональным параметрам \Bitrix\Main\Entity\DataManager::getList.
getConnectionName() // метод возвращает имя соединения для сущности. 12.0.9
getCount($filter = array(), array $cache = array()) // метод выполняет COUNT запрос к сущности и возвращает результат. 12.0.10
getEntity() // метод возвращает объект сущности.
getList(array $parameters = array()) // получение элементов, подробнее было выше
getMap() // метод возвращает описание карты сущностей. 12.0.7
getRow(array $parameters) // метод возвращает один столбец (или null) по параметрам для \Bitrix\Main\Entity\DataManager::getList.
getRowById($id) // метод возвращает один столбец (или null) по первичному ключу сущности. 14.0.0
getTableName() // метод возвращает имя таблицы БД для сущности. 12.0.7
query() // метод создаёт и возвращает объект запроса для сущности.
enableCrypto($field, $table = null, $mode = true) // метод устанавливает флаг поддержки шифрования для поля. 17.5.14
cryptoEnabled($field, $table = null) // метод возвращает true если шифрование разрешено для поля. 17.5.14
addMulti($rows, $ignoreEvents = false)
updateMulti($primaries, $data, $ignoreEvents = false)
// Следующий методы заблокированы у инфоблоков
add(array $data) // добавление элемента
delete($primary) // удаление элемента по ID
update($primary, array $data) // обновление элемента по IDАльтернативный вариант получения данных
Альтернативный вариант получения данных с помощью Bitrix\Main\Entity\Query:
// Получение символьных кодов свойств с помощью ORM
use Bitrix\Iblock\PropertyTable;
$propertyType = 'N'; //Тип свойства: 'N' - число
$query = PropertyTable::query(); //Получаем объект Bitrix\Main\ORM\Query\Query
$query->setFilter([ //Устанавливаем фильтр
'=IBLOCK_ID' => CATALOG_IBLOCK_ID,
'=PROPERTY_TYPE' => $propertyType,
]);
$query->setSelect(['CODE']); //Устанавливаем список получаемых полей
$properties = $query->exec()->fetchAll(); //Делаем запрос и получаем данные в виде массиваБолее сложный пример получения данных с помощью Bitrix\Main\Entity\Query:
use Bitrix\Main\Entity\Query;
use Bitrix\Main\Entity\ExpressionField;
use Bitrix\Main\Entity\ReferenceField;
$query = new Query(Bitrix\Iblock\ElementPropertyTable::getEntity());
$query->setSelect([
"VALUE",
new ExpressionField("LENGTH_VALUE", "LENGTH(%s)", "VALUE") // Вычисляемое выражение (подробности ниже)
]);
$query->setFilter([
'IBLOCK_PROPERTY_ID' => PROP_AUCTION_STATUS_ID,
'IBLOCK_ELEMENT_ID' => $auctionId
]);
$query->registerRuntimeField(new ReferenceField( //Подзапрос в другую таблицу (подробности ниже)
"ENUM",
"Bitrix\Iblock\PropertyEnumerationTable",
["=this.VALUE" => "ref.ID"]
));
$result = $query->exec(); // Выполнение запроса
while ($row = $result->fetch()) { // Обработка результатов в виде массива
print_r($row);
}
Вычисляемое поле
Вычисляемое поле создается с помощью класса Bitrix\Main\Entity\ExpressionField. В конструктор этого класса передаются три аргумента:
- Название поля, которое мы получим в итоге — «LENGTH_VALUE».
- Выражение, которое будет использоваться для вычисления значения поля — «LENGTH(%s)».
- Имя поля, значение которого будет использоваться в выражении — «VALUE».
Таким образом, вычисляемое поле «LENGTH_VALUE» будет содержать длину значения поля «VALUE».
Bitrix\Main\Entity\ExpressionField позволяет использовать различные выражения для вычисления значений вычисляемых полей. Некоторые из наиболее часто используемых выражений:
- Математические выражения: +, -, *, /, %. Например, вычисление суммы двух полей: «%s + %s», где %s — это специальный символ, который будет заменен на значения полей.
- Функции: COUNT(), SUM(), AVG(), MIN(), MAX(), LENGTH(), CONCAT(), SUBSTRING(), DATE_FORMAT(), NOW(), UNIX_TIMESTAMP(), FROM_UNIXTIME(), и другие. Например, вычисление среднего значения поля: «AVG(%s)».
- Логические выражения: AND, OR, NOT, =, !=, <, >, <=, >=, BETWEEN, IN, LIKE, REGEXP. Например, выборка записей, где значение поля больше 10: «%s > 10».
- Выражения с условиями: CASE, IF, IFNULL, COALESCE. Например, вычисление значения поля на основе условия: «CASE WHEN %s > 10 THEN ‘больше 10’ ELSE ‘меньше или равно 10’ END».
- Выражения с подзапросами: EXISTS, NOT EXISTS, IN, NOT IN, ANY, ALL, SOME, UNION, INTERSECT, EXCEPT. Например, выборка записей, где значение поля равно максимальному значению в другой таблице: «%s = (SELECT MAX(field) FROM table2)».
Это лишь некоторые примеры выражений, которые можно использовать в Bitrix\Main\Entity\ExpressionField. В зависимости от конкретной задачи можно использовать и другие выражения.
Описание подзапросов есть ниже при использовании Bitrix\Main\Entity\Query, они делаются так же, как и через описанный ниже метод.
Работа с кастомными таблицами
Чтобы работать с кастомной таблицей, сначала нужно создать класс для работы с ней. Пример такого класса:
namespace Custom\Model; //описываем пространство имен для нашей таблицы
use Bitrix\Main\Entity; //подключаем для работы с сущностями БД (CRUD)
class DraftTable extends Entity\DataManager //обязательно наследовать свою таблицу от Entity\DataManager И обязательно чтобы название класса заканчивалось на ...Table
{
public static function getTableName(): string //вернет название таблицы
{
return 'custom_draft_table';
}
public static function getMap() //при создании кастомной таблицы, в ней будут созданы такие поля
{
return array(
new Entity\IntegerField(
'ID',
array(
'primary' => true,
'autocomplete' => true,
)),
new Entity\IntegerField(
'USER_ID',
array(
'required' => true,
)),
new Entity\DatetimeField(
'DATE_CREATE',
array(
'default_value' => new \Bitrix\Main\Type\DateTime(),
)),
new Entity\TextField('INFO'),
);
}
public static function dropTable() //метод для удаления таблицы
{
$connection = \Bitrix\Main\Application::getConnection();
$connection->dropTable(self::getTableName());
}
}Посмотреть типы данных и атрибуты при создании полей кастомной таблицы, можно в статье «Типы данных при создании кастомных таблиц«.
В рамках соблюдения стандартов кодирования, битрикс рекомендует называть поля таблиц в верхнем регистре. Для добавления таблицы воспользуемся следующим кодом:
if (!Custom\Model\DraftTable::getEntity()->getConnection()->isTableExists(Custom\Model\DraftTable::getTableName())) {
Custom\Model\DraftTable::getEntity()->createDbTable();
}Для добавления записи в созданную таблицу можно использовать следующий код (вернет объект Bitrix\Main\ORM\Data\AddResult). Для получения ID новой записи использовать GetId
use Custom\Model\DraftTable;
$result = DraftTable::add(array(
'USER_ID' => $USER->GetID(),
'DATE_CREATE' => new DateTime(),
'INFO' => json_encode($itemInfoDraft),
));Для обновления записи в кастомной таблице битрикс можно использовать следующий код:
use Custom\Model\DraftTable;
$result = DraftTable::update(
$primaryKeyId, //ID записи в таблице
array(
'USER_ID' => $newUserId,
'DATE_CREATE' => new DateTime(),
'INFO' => json_encode($newInfo),
));Для удаления записи из кастомной таблицы используем код:
use Custom\Model\DraftTable;
// Удаляем запись
$result = DraftTable::delete($primaryKeyId);Для проверки исполнения кода (добавления/удаления/обновления), можно использовать следующий код:
if ($result->isSuccess()) {
echo 'Запись успешно удалена.';
} else {
$errors = $result->getErrorMessages();
echo 'Ошибка при удалении записи: ' . implode(', ', $errors);
}Во всех случаях, $result будет содержать объект результата действия (например, Bitrix\Main\ORM\Data\AddResult или Bitrix\Main\ORM\Data\DeleteResult).
Подзапросы с использованием метода join() (через runtime)
Чтобы не делать несколько отдельных запросов в БД, можно использовать функционал подзапросов. Вот пример кода:
$auctionStatus = \Bitrix\Iblock\ElementPropertyTable::getList([
'filter' => [ // Фильтруем значения - для таблицы ElementPropertyTable
'IBLOCK_PROPERTY_ID' => PROP_AUCTION_STATUS_DATA['ID'],
'IBLOCK_ELEMENT_ID' => $auctionId
],
'select' => [ // Выбираем поле 'VALUE' из таблицы ElementPropertyTable и поле 'XML_ID' из таблицы PropertyEnumerationTable
'VALUE',
//Использовать одно из трех значений:
//'ENUM.XML_ID', // 1. Можно использовать такую форму записи. Тогда результат выборки будет таким: IBLOCK_ELEMENT_PROPERTY_ENUM_XML_ID => 25
'ENUM_XML_ID' => 'ENUM.XML_ID' // 2. Чтобы название было аккуратным, прописываем "ENUM_XML_ID". Именно такой ключ будет иметь выбранное из БД значение. Теперь результат выборки будет таким: ENUM_XML_ID => 25
//'ENUM_XML_ID' => 'ENUM' // 3. Результат выборки - все значения из таблицы PropertyEnumerationTable для выбранного ID. Ну и VALUE (из таблицы ElementPropertyTable)
],
'runtime' => [
new \Bitrix\Main\Entity\ReferenceField(
'ENUM', // Имя для создаваемого объекта ReferenceField. Это имя может быть любым
'Bitrix\Iblock\PropertyEnumerationTable', // Добавляем ссылку на таблицу PropertyEnumerationTable с помощью метода ReferenceField()
array('=this.VALUE' => 'ref.ID') // Связываем поле VALUE из таблицы ElementPropertyTable и поле ID из таблицы PropertyEnumerationTable - для фильтрации по ID
)
]
])->fetch();Строка «ENUM» в «ReferenceField» — это имя для создаваемого объекта ReferenceField. Это имя может быть любым, но обычно используется имя, которое отражает суть связи между таблицами.Таким образом, строка «ENUM.XML_ID» означает, что мы делаем выборку поля «XML_ID» из таблицы «PropertyEnumerationTable».
Работа с инфоблоками и любыми данными инфоблоков
Для работы с инфоблоками и любыми данными, которые в них находятся можно использовать следующую конструкцию:
$iblockClass = \Bitrix\Iblock\Iblock::wakeUp($iblockId)->getEntityDataClass();Не стоит забывать, что в объекте инфоблока будет храниться информация о самом инфоблоке, включая свойства настройки и прочие параметры. Это может включать название инфоблока, его тип, доступные поля и свойства, права доступа, настройки сортировки, фильтры и другие атрибуты, которые определяют поведение и структуру инфоблока. Также, с помощью объекта, содержащегося в $iblockClass, можно работать с элементами инфоблока.
Не стоит забывать — чтобы метод wakeUp() отработал без ошибок, в инфоблоке должна быть задана настройка «Символьный код API».
Пример выборки данных для элемента инфоблока, включая ссылку на детальную страницу, значение свойства и прочее:
$iblockClass = \Bitrix\Iblock\Iblock::wakeUp($arParams['IBLOCK_ID'])->getEntityDataClass(); //получаем объект
$select = [
'PREVIEW_PICTURE',
'MAIN_VALUE' => 'MAIN.VALUE', //свойство "MAIN", из которого мы забираем VALUE для конкретного элемента инфоблока
'IBLOCK_SECTION_ID', //ID раздела
'SHOW_COUNTER', //кастомное значение в таблице элементов
'DETAIL_PAGE_URL_RAW' => 'IBLOCK.DETAIL_PAGE_URL', //получаем DETAIL_PAGE_URL
'CODE'
];
$elCatalog = $iblockClass::getList([
'order' => array('ACTIVE_FROM'=>'DESC','ID'=>'DESC'),
'filter' => array(
'IBLOCK_ID'=>$arParams['IBLOCK_ID'],
'ACTIVE'=>'Y',
//'MAIN_VALUE'=> '41' // в $select задана MAIN_VALUE, значит здесь пишем так же
'LOGIC' => 'OR',
[
'MAIN_VALUE' => '41',
],
[
'MAIN_VALUE' => '42', // Второе условие для "или"
],
),
'limit' => 1, //достаем всего один элемент
'select' => $select
])->fetch();
$elCatalog['DETAIL_PAGE_URL'] = \CIBlock::ReplaceDetailUrl($elCatalog["DETAIL_PAGE_URL_RAW"], $elCatalog, true, "E"); //получаем URL деталки элемента (для корректного формирования обязательно передавать "IBLOCK_ID", "CODE", "IBLOCK_SECTION_ID", "IBLOCK.DETAIL_PAGE_URL_RAV")
$elCatalog['PREVIEW_PICTURE'] = CFile::GetFileArray($elCatalog['PREVIEW_PICTURE']); //получаем массив с данными по ID изображенияПримеры использования
Выборка ID, NAME для элементов инфоблока (например, каталога):
$all_el_catalog = \Bitrix\Iblock\ElementTable::getList([
'select' => ['ID', 'NAME'],
'filter' => ['IBLOCK_ID' => $ib_id],
])->fetchAll();Выборка ID элементов по свойству, у которых:
- заполнено свойство $prop_id;
- ID элемента находится в массиве $all_el_catalog
$all_el_catalog = \Bitrix\Iblock\ElementTable::getList([
'select' => ['ID', 'NAME'],
'filter' => ['IBLOCK_ID' => $ib_id],
])->fetchAll();Выборка данных из кастомной таблицы:
use \Bitrix\Main;
$test_xml_id = 'fffff';
$query = "SEL ECT `DATA` FROM user_table WHERE `XML_ID` = '$test_xml_id'";
try
{
$connection = Main\Application::getInstance()->getConnection();
$queryResult = $connection->query($query);
foreach ($queryResult as $data)
{
var_dump( (array) $data );
}
}
catch( Main\DB\SqlException $e )
{
var_dump($e->getMessage());
}Получение ID раздела по его символьному коду:
$section_id = \Bitrix\Iblock\SectionTable::getList([
'select' => ['ID'],
'filter' => ['CODE' => $section_code],
])->fetch();
Об авторе
Сергей Житников - Веб-разработчик
Занимаюсь веб-разработкой более 5 лет. Специализируюсь на создании адаптивных сайтов и веб-приложений на HTML5, CSS3 и JavaScript. Работаю с популярными CMS и фреймворками, а также уделяю большое внимание оптимизации производительности и чистоте кода.
Есть проект или идея? Буду рад помочь!
Связаться со мной