Дата последнего изменения: 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.