Объектные кирпичи (Objectbricks)
Общее
С помощью Objectbricks объекты можно расширять без изменения определения класса. Это особенно полезно при хранении данных о продуктах. Часто существует базовый набор атрибутов, которые есть у всех продуктов. Но при этом множество атрибутов присутствуют только у части продуктов.
Например, у продавца автомобильных комплектующих тормоза имеют другие атрибуты, чем шины, диски или навигационные системы. Старый подход — создать класс продукта, который содержит все возможные атрибуты всех типов продуктов. Это работает, но большинство полей будут пустыми, а редактор объекта станет неудобным.
Новый подход — использовать Objectbricks. Класс продукта содержит только те атрибуты, которые есть у всех продуктов (например: name, article number, manufacturer, price и т.д.). Для каждой группы продуктов создаётся отдельный objectbrick. Objectbrick для тормозов содержит атрибуты вроде diameter, material. Objectbrick для шин — dimension, type, maximum speed и т.д.
При создании объекта продукта типа «шина» к нему добавляется соответствующий objectbrick, и этот объект получает все поля шин.

К одному объекту можно добавить несколько Objectbricks, но не более одной копии каждого типа objectbrick. Это главное отличие от Fieldcollections. Поскольку для каждого objectbrick допустима только одна инстанция на объект, Objectbricks полностью поддерживают наследование на уровне полей: каждый атрибут objectbrick можно переопределить в дочерних объектах.

Несмотря на гибкость, модель данных в базе остаётся аккуратной и структурированной. Атрибуты objectbrick определяются так же, как и в Fieldcollections.
Определение Objectbrick
Objectbricks определяются тем же способом, что и объекты и Fieldcollections, и поддерживают похожие типы данных.

Чтобы можно было добавлять Objectbrick в объект, нужно выполнить два шага:
- В списке компонентов данных при создании класса выбрать тип данных Objectbricks. Этот тип данных определяет, куда можно добавлять Objectbricks. Поле этого типа данных должно быть добавлено в класс объекта.

- В определении Objectbrick класс объекта и требуемое поле должны быть добавлены к разрешенным классам.

В определении самого Objectbrick необходимо добавить класс объекта и имя поля в список допустимых классов (allowed classes). В определении Objectbricks можно также указать родительский класс — способ такой же, как и для обычных классов (см. раздел про Parent Class for Objects section в документации).
Работа через PHP API
Получение Objectbricks
После сохранения класса объекта для каждого поля типа Objectbrick этого класса создаётся собственный класс-обёртка с геттерами для каждого разрешённого Objectbrick. В нашем примере этот класс данных будет выглядеть следующим образом.
Геттер $product->getBricks() возвращает экземпляр этого класса, заполненный Objectbricks конкретного $product. Вызов этого геттера возвращает класс Objectbrick с его геттерами для атрибутов.
//получение данных Objectbrick
$product = DataObject\Product::getById(4);
$tiretype = $product->getBricks()->getTire()->getTiretype();
Установка данных работает так же, как и получение. Для каждого геттера есть соответствующий сеттер. При сохранении объекта сохраняются и его bricks.
//установка данных Objectbrick
$product = DataObject\Product::getById(4);
$product->getBricks()->getTire()->setTiretype("Winter");
$product->save();
//добавление нового Objectbrick к объекту
$product = new DataObject\Product();
$product->setKey("testproduct");
$product->setParent(DataObject\Product::getById(4));
$product->setName("testproduct");
$tireBrick = new DataObject\Objectbrick\Data\Tire($product);
$tireBrick->setTiretype("allyear");
$product->getBricks()->setTire($tireBrick);
$product->save();
Удаление Objectbricks через код
//удалить все Objectbricks из поля Objectbrick
$product->getBricks()->delete($product);
$product->save();
$productBricks = $product->getBricks();
$tireBrick = $productBricks->getTire();
if ($tireBrick) {
$tireBrick->setDoDelete(true);
}
$product->save();
Запросы к данным Objectbrick
Данные Objectbricks можно запрашивать так же, как и данные fieldcollections. Необходимо добавить нужные Objectbricks в объект DataObject\Listing, после чего обращаться к атрибутам Objectbrick в условии запроса.
//запрос объектов по данным Objectbrick
$productList = DataObject\Product::getList([
/* перечислите здесь необходимые Objectbricks для условий */
"objectbricks" => ["Tire","Brake"],
/* в условии обращайтесь к атрибутам как OBJECTBRICKNAME.ATTRIBUTENAME */
"condition" => "Tire.dimension > 200"
]);
Если требуется получить список объектов, которые имеют конкретный Objectbrick, можно в условии проверить значение fieldname.
//вернуть все продукты, у которых есть Objectbrick "Tire"
$productList = DataObject\Product::getList([
/* перечислите здесь необходимые Objectbricks для условий */
"objectbricks" => ["Tire"],
/* в условии обращайтесь к атрибутам как OBJECTBRICKNAME.ATTRIBUTENAME */
"condition" => "Tire.fieldname != ''"
]);
Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.