Перейти к основному содержимому

Отношения

Поля данных объектных отношений "Многие к одному", "Многие ко многим" и "Многие ко многим"

Many‑To‑One, Many‑To‑Many и Many‑To‑Many Objects являются чисто реляционными типами данных, что означает, что они представляют отношение к другому элементу Pimcore (документу, ассету, объекту). Типы Many‑To‑One и Many‑To‑Many могут хранить связи с любыми элементами Pimcore. В определении поля класса объекта можно настроить, какие типы и подтипы элементов разрешены.

Поле Many‑To‑Many Object позволяет устанавливать связи только с одним или несколькими объектами данных, но не с другими типами элементов; поэтому настройки ограничений в этом случае применимы только к классам объектов.

Для виджета ввода можно задать ширину и высоту в настройках класса. Для Many‑To‑One можно настроить только ширину, так как оно представлено одним полем для перетаскивания (drop area). Более подробное описание отложенной загрузки приведено ниже в разделе о связях и отложенной загрузке.

Виджеты ввода для всех трех типов данных, связанных с отношениями, представлены областями перетаскивания, которые позволяют перетаскивать элементы из дерева слева к цели перетаскивания в макете объекта.

Кроме перетаскивания, элементы можно искать и выбирать прямо из виджета. Для объектов также возможно создать новый объект прямо из виджета и выбрать его.

Поле отношения

Фильтрация по связям через PHP API

Чистые реляционные типы хранятся в отдельной таблице базы данных object_relations_ID. В соответствующем представлении object_~ID~, используемом для запросов, поля связей суммируются в виде списка ID связанных элементов, разделенных запятыми. Следовательно, если кому-то нужно создать список объектов с условием фильтрации по столбцу отношения, это может быть достигнуто следующим образом:

$relationId = 162;  
$list = new \Pimcore\Model\DataObject\Example\Listing();
$list->setCondition("mySingleRelation__id = ".$relationId);
$objects=$list->load();


$relationId = 345;
$list = new \Pimcore\Model\DataObject\Example\Listing();
$list->setCondition("myManyToManyRelations like '%,object|".$relationId.",%'");
$objects=$list->load();

Назначение связей через PHP API

Чтобы установить поле Many‑To‑One, в сеттер передаётся один элемент Pimcore. Для Many‑To‑Many и Many‑To‑Many Objects — передаётся массив элементов:

use Pimcore\Model\DataObject;  
use Pimcore\Model\Document;
use Pimcore\Model\Asset;

$object = DataObject::getById(12345);

$object->setMyManyToOneField(Document::getById(23));

$object->setMyManyToManyField([
Asset::getById(350),
DataObject::getByPath("/products/testproduct")
]);

$object->setMyManyToManyObjectField([
DataObject\Product::getById(98),
DataObject\Product::getById(99)
]);

$object->save();

Удаление связей через PHP API

Чтобы удалить все элементы из поля Many‑To‑Many данного объекта, можно вызвать сеттер с null или с пустым массивом:

$object->setMyManyToManyField([]);  

//то же самое
$object->setMyManyToManyField(null);

Внутренне сеттер устанавливает значение в пустой массив независимо от того, передали ли вы пустой массив или null.

Непубликованные связи

По умолчанию непубликованные связанные элементы не возвращаются. Это поведение можно отключить следующим образом:

//также включаем возвращение непубликованных связей  
DataObject::setHideUnpublished(false);
//получить связанный объект, даже если он не опубликован
$relationObject = $relation->getObject();
//вернуть обычное поведение
DataObject::setHideUnpublished(true);

Разрешить встроенную загрузку ассета

Вы можете включить встроенную загрузку ассетов в отношения, если вы установите флажок "Allow inline download".
Если отношение — это ассет, он будет загружен напрямую. Если отношение — это папка, будет загружен файл zip.

Отключить полную очистку связей

Если нужно запретить возможность очистить всю связь одним действием, снимите галочку "Allow to clear all relations of this field" в определении класса.

Advanced Many-To-One Object Relation

Этот тип является расширением Many‑To‑One Object. Для каждой привязанной сущности помимо самой связи можно сохранить дополнительные метаданные. Типы метаданных могут быть: текст, число, выбор (select) или булево значение.

Ограничение: здесь может быть указана только одна разрешённая класс‑модель. В силу этого ограничения возможно отображать поля данных назначаемых объектов прямо в списке связей. Какие колонки метаданных доступны и какие поля назначаемых объектов отображаются задаётся при определении класса.

Конфигурация Advanced Many-To-One Object Relation

Приведенное определение класса приводит к следующему списку в редакторе объектов. первые два столбца обычно содержат id и title назначаемого объекта; остальные столбцы — это колонки метаданных, которые можно редактировать прямо в списке.

Поле Advanced Many-To-One Object Relation

Остальная функциональность идентична обычным типам данных.

Доступ к объектам с метаданными через PHP API

use Pimcore\Model\DataObject;  

$object = DataObject::getById(73585);

//получение списка назначенных объектов с метаданными (массив объектов DataObject\Data\ObjectMetadata)
$objects = $object->getMetadata();

//получить первый элемент
$relation = $objects[0];

//получить связанный объект
$relationObject = $relation->getObject();

//доступ к метаданным через геттеры (имя геттера = ключ колонки метаданных)
$metaText = $relation->getText();
$metaNumber = $relation->getNumber();
$metaSelect = $relation->getSelect();
$metaBool = $relation->getBool();

//установка данных через сеттеры
$relation->setText("MetaText2");
$relation->setNumber(5512);
$object->save();

Сохранение объектов с метаданными

use Pimcore\Model\DataObject;  

//загрузить ваш объект (в котором будем сохранять метаданные)
$object = DataObject::getById(73585);

//создать пустой массив для объектов метаданных
$objectArray = [];

//пройтись по списку объектов (или массиву) и создать ObjectMetadata
foreach ($yourObjectsList as $yourObject) {

//создать объект метаданных, на который ссылается "yourObject".
$objectMetadata = new DataObject\Data\ObjectMetadata('metadata', ['text', 'number'], $yourObject);
//задать в поле метаданные (поле Text) значение "Метаданные".
$objectMetadata->setText('Metadata');
//задать в поле метаданных (поле Number) значение 23
$objectMetadata->setNumber(23);

//добавить в пустой массив "objectArray"
$objectArray[] = $objectMetadata;
}

//установить массив метаданных в объект
$object->setMetadata($objectArray);

// сохранить
$object->save();

Advanced Many-To-Many Relation

Этот тип похож на Advanced Many-To-One Object Relation тем, что к связи можно добавлять дополнительные данные.

Главное отличие: в список связей можно добавлять элементы любых типов (документы, ассеты и объекты)б типы можно смешивать. В остальном действуют те же правила, что и для стандартного Many‑To‑Many.

API почти идентично, но вместо ObjectMetadata используется ElementMetadata.

use Pimcore\Model\DataObject;  
use Pimcore\Model\Document;

$referencedElement = Document::getById(123);
$references = [];
$elementMetadata = new DataObject\Data\ElementMetadata('metadata', ['text', 'number'], $referencedElement);

//задайте в поле метаданных (поле Text) значение "my lovely text"
$elementMetadata->setText('my lovely text');

//задать в поле метаданных (поле Number) значение 23
$elementMetadata->setNumber(23);


$references[] = $elementMetadata;

//установить массив метаданных в объект
$object->setMetadata($references);

Отложенная загрузка (Lazy Loading)

Обратите внимание, что начиная с версии 6.5.0, для отношений всегда используется отложенная загрузка. Параметр конфигурации был удален.

Когда объект загружается из базы данных или кеша, все связанные объекты НЕ загружаются вместе с ним, если поле помечено как лениво загружаемое. Особенно для Many‑To‑Many легко накопить очень много связей, что замедляет загрузку объекта или списка объектов.

Решение — пометить Many‑To‑Many поля как lazy loading в определении класса.

Отложенная загрузка

Атрибуты, помеченные как lazy loaded, подгружаются из database/cache только тогда, когда вызывается их геттер. В примере это значит, что данные Many‑To‑Many будут загружены только при вызове $object->getMyManyToManyField();.

Зависимости

В Pimcore есть несколько типов полей, которые представляют связь с другим элементом. К «чистым» реляционным типам относятся:

  • Many-To-One Relation
  • Many-To-Many Relation
  • Advanced Many-To-Many Relation
  • Many-To-Many Object Relation
  • Advanced Many-To-One Object Relation

Кроме них, есть типы данных, которые также представляют связь, но они не отражаются в таблицах object_relation_.., поскольку являются специальными и не чисто реляционными (например, можно спорить по поводу image, но сейчас он не классифицируется как чистый relation type):

  • Image
  • Link
  • Wysiwyg

Все эти связи создают зависимости между элементами. То есть зависимый элемент отображается в вкладке dependecies у обоих элементов, и Pimcore выдаст предупреждение при попытке удалить элемент, у которого есть зависимости.

Зависимости


Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.