Дата последнего изменения: 11.05.2022
Коллекции позволяют совершать групповые операции над содержащимися в ней элементами.
Метод save() в случае с новыми объектами выполняет их первичное сохранение, формируя один групповой запрос:
use \Bitrix\Main\Test\Typography\Books;
use \Bitrix\Main\Test\Typography\Book;
$books = new Books;
$books[] = (new Book)->setTitle('Title 112');
$books[] = (new Book)->setTitle('Title 113');
$books[] = (new Book)->setTitle('Title 114');
$books->save(true);
// INSERT INTO ... (`TITLE`, `ISBN`) VALUES
('Title 112', DEFAULT),
('Title 113', DEFAULT),
('Title 114', '114-000')
При этом в метод передан параметр $ignoreEvents = true, отменяющий выполнение событий ORM во время добавления записей. Дело в том, что именно при мульти-вставке с автоинкрементным полем (ID) невозможно получить множественные значения этого поля, как это возможно при вставке одной записи с помощью функций вроде mysqli_insert_id().
В остальных случаях, когда в сущности нет автоинкрементных полей, выполнение событий остается на усмотрение разработчика. По умолчанию события будут выполняться.
Метод save() в случае с уже существующими, но измененными объектами, выполняет их сохранение одним запросом UPDATE:
use \Bitrix\Main\Test\Typography\PublisherTable;
use \Bitrix\Main\Test\Typography\BookTable;
$books = BookTable::getList()->fetchCollection();
$publisher = PublisherTable::wakeUpObject(254);
foreach ($books as $book)
{
$book->setPublisher($publisher);
}
$books->save();
// UPDATE ... SET `PUBLISHER_ID` = '254'
WHERE `ID` IN ('1', '2')
Групповое обновление сработает только в случае, если набор изменных данных единый для всех объектов. Если же хотя бы в одном объекте измененные данные отличаются, то все записи будут сохранены по отдельности.
Как и в случае с добавлением, при обновлении можно отключать выполнение событий параметром $ignoreEvents в методе save(). По умолчанию они выполняются для каждого элемента коллекции.
Коллекционная операция fill является прекрасной альтернативой аналогичной операции в Объекте, выполненной в цикле. В случае с циклом количество запросов к базе данных будет равно количеству объектов:
/** @var \Bitrix\Main\Test\Typography\Book[] $books */
$books = [
\Bitrix\Main\Test\Typography\Book::wakeUp(1),
\Bitrix\Main\Test\Typography\Book::wakeUp(2)
];
foreach ($books as $book)
{
$book->fill();
// SELECT ... WHERE ID = ...
// так делать не надо!
}
В случае же с коллекцией запрос будет только один:
$books = new \Bitrix\Main\Test\Typography\Books; // или $books = \Bitrix\Main\Test\Typography\BookTable::createCollection(); $books[] = \Bitrix\Main\Test\Typography\Book::wakeUp(1); $books[] = \Bitrix\Main\Test\Typography\Book::wakeUp(2); $books->fill(); // SELECT ... WHERE ID IN(1,2)
Как и в случае с объектами, в качестве параметров в fill можно передавать массив имен полей для заполнения или маску типа:
$books->fill(['TITLE', 'PUBLISHER_ID']); $books->fill(\Bitrix\Main\ORM\Fields\FieldTypeMask::FLAT);
Более подробно возможные значения параметра описаны в fill Объектов.
Не самый редкий сценарий - получить из результата запроса список значений отдельного поля. В обычном случае это может выглядеть так:
$books = \Bitrix\Main\Test\Typography\BookTable::getList()
->fetchCollection();
$titles = [];
foreach ($books as $book)
{
$titles[] = $book->getTitle();
}
Именованный групповой "геттер" позволяет сократить такой цикл до одной строчки кода:
$books = \Bitrix\Main\Test\Typography\BookTable::getList() ->fetchCollection(); $titles = $books->getTitleList();
Такие "геттеры" доступны для всех полей сущности и описываются в аннотациях для IDE.