Привязка к элементам инфоблока в своих таблицах с использованием ORM с применением фильтра инфоблоков
В данной статье рассматривается практический пример работы с дополнительными таблицами в системе «1С-Битрикс», где используется привязка к элементам инфоблока через их уникальные идентификаторы (ID). Мы покажем, как эффективно применять ORM (Object-Relational Mapping) и фильтры инфоблоков для получения нужных данных.
Тестовый стенд
Для демонстрации примера будем использовать шаблон «Интернет-магазин», входящий в поставку «1С-Битрикс: Управление сайтом» редакции «Малый бизнес» и выше.
Создание дополнительной таблицы
Начнем с создания таблицы, которая будет хранить дополнительные данные для каждого элемента инфоблока. В нашем примере это будет дополнительное описание товара.
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields;
class TestTable extends DataManager
{
public static function getTableName()
{
return 'devbx_test_001';
}
public static function getMap()
{
return [
(new Fields\IntegerField('ELEMENT_ID'))->configurePrimary(true),
(new Fields\TextField('MY_DESCRIPTION')),
];
}
}
Заполнение таблицы тестовыми данными
Теперь заполним нашу таблицу случайными данными. Для этого используем генератор текстов Lorem Ipsum.
$entity = TestTable::getEntity();
//проверяем если таблица не существует, создадим ее
if (!$entity->getConnection()->isTableExists($entity->getDBTableName()))
{
$entity->createDbTable();
for ($i=1;$i<20;$i++)
{
//возьмем рандомные тексты Lorem ipsum
$lipsum = \Bitrix\Main\Web\Json::decode(file_get_contents('http://lipsum.com/feed/json'));
TestTable::add([
'ELEMENT_ID' => $i,
'MY_DESCRIPTION' => $lipsum['feed']['lipsum']
]);
}
}
Применение фильтра инфоблоков
Далее нам необходимо извлечь из нашей таблицы описания тех товаров, которые изготовлены из хлопка и трикотажа. Для этого воспользуемся классом CIBlockElement, чтобы сформировать фильтр и получить нужные элементы.
Формирование фильтра
use Bitrix\Main\DB\SqlExpression;
\Bitrix\Main\Loader::includeModule('iblock');
$el = new \CIBlockElement();
$el->prepareSql(
['ID'],
[
'IBLOCK_ID' => 2,
'=PROPERTY_MATERIAL' => ['хлопок', 'трикотаж']
],
false,
[] //убираем сортировку, иначе будет добавлено в SELECT нашего под запроса
);
$subQuery = "SELECT ".$el->sSelect." FROM ".$el->sFrom." WHERE 1=1 ".$el->sWhere;
Извлечение данных
Используя сформированный подзапрос, получаем данные из нашей таблицы.
$iterator = TestTable::getList([
'filter' => [
'@ELEMENT_ID' => new SqlExpression($subQuery),
],
'select' => [
'ELEMENT_ID',
'MY_DESCRIPTION'
]
]);
while ($row = $iterator->fetch())
{
print_r($row);
}
Просмотр итогового SQL-запроса
Чтобы увидеть, какой SQL-запрос был сформирован, выполните следующий код:
echo TestTable::query()
->setFilter([
'@ELEMENT_ID' => new SqlExpression($subQuery),
])
->setSelect([
'ELEMENT_ID',
'MY_DESCRIPTION'
])->getQuery();
Результатом выполнения данного кода будет такой SQL-запрос:
SELECT
`test`.`ELEMENT_ID` AS `ELEMENT_ID`,
`test`.`MY_DESCRIPTION` AS `MY_DESCRIPTION`
FROM `devbx_test_001` `test`
WHERE `test`.`ELEMENT_ID` IN (SELECT DISTINCT BE.ID as ID FROM
b_iblock B
INNER JOIN b_lang L ON B.LID=L.LID
INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID
INNER JOIN b_iblock_property FP0 ON FP0.IBLOCK_ID = B.ID AND FP0.CODE='MATERIAL'
INNER JOIN b_iblock_element_property FPV0 ON FPV0.IBLOCK_PROPERTY_ID = FP0.ID AND FPV0.IBLOCK_ELEMENT_ID = BE.ID
WHERE 1=1
AND (
((((BE.IBLOCK_ID = 2))))
AND ((((FPV0.VALUE = 'хлопок')) OR ((FPV0.VALUE = 'трикотаж'))))
)
AND (((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL))))
Таким образом, мы успешно извлекли необходимые данные из таблицы, используя механизм подзапросов и фильтров в «1С-Битрикс».
Эта статья демонстрирует эффективный способ работы с дополнительными таблицами и фильтрами инфоблоков в «1С-Битрикс».