Работа с объектами через PHP API
Pimcore предоставляет объектно‑ориентированный PHP API для работы с объектами (Data Objects). Pimcore генерирует PHP‑классы для каждого класса объектов, что позволяет удобно работать с объектами через IDE (автодополнение, подсказки и т.д.).
операции CRUD
Следующий фрагмент кода показывает, как получить доступ, создавать и изменять объект программно:
<?php
use \Pimcore\Model\DataObject;
// Создание нового объекта
$newObject = new DataObject\Myclassname();
$newObject->setKey(\Pimcore\Model\Element\Service::getValidKey('New Name', 'object'));
$newObject->setParentId(123);
$newObject->setName("New Name");
$newObject->setDescription("Some Text");
// не обязательный параметр позволяет передать дополнительную информацию
// текущая поддерживаемая опция:
// * versionNote: заметка для версии (см. вкладку версий)
$newObject->save(["versionNote" => "my new version"]);
//получение объектов
$myObject = DataObject\Myclassname::getById(167);
//чтение данных
$myObject->getName();
$myObject->getDescription();
// получение объекта по внешнему идентификатору (foreign id)
$city = DataObject\City::getByZip(5020,1);
// получение объекта по id, когда тип неизвестен
$object = DataObject::getById(235);
// получение объекта по пути
$object = DataObject::getByPath("/path/to/the/object");
// получение объектов, соответствующих определенному набору типов объектов (по умолчанию используется выборка объектов и их вариантов)
$product = DataObject\Product::getByColor('purple', 1, 0, [Product::OBJECT_TYPE_VARIANT]);
//обновление и сохранение объекта
$myObject->setName("My Name");
$myObject->save();
//удаление объекта
$city->delete();
При использовании сгенерированных классов имя PHP‑класса начинается с заглавной буквы. Пример:
Имя класса:product
PHP‑класс:DataObject\Product
Списки объектов
Как только данные становятся доступны в структурированном виде, к ним становится не только удобнее обращаться, но и их можно фильтровать, сортировать, группировать и интуитивно отображать с помощью списка объектов. Более того, данные можно очень легко экспортировать не только программно, но и с помощью экспорта объектов Pimcore в формате csv.
Списки объектов - это простой способ извлечения объектов из Pimcore, позволяющий при этом фильтровать и сортировать данные. Списки объектов также оснащены встроенным пагинатором, который упрощает отображение результатов в виде постраничной таблицы.
При работе со списками объектов пользовательские маршруты удобны при реализации подробных представлений объектов. Пользовательские маршруты позволяют направлять запросы на определенные страницы сведений, даже если запрос не отображает путь к документу, а соответствует определенному маршруту. Для получения дополнительной информации ознакомьтесь с URL-адресами, основанными на пользовательских маршрутах.
Для каждого определённого класса автоматически создаётся класс Listing. Пример получения объектов класса Myclassname:
<?php
use \Pimcore\Model\DataObject;
$entries = new DataObject\Myclassname\Listing();
$entries->setOffset($offset);
$entries->setLimit($perPage);
$entries->setOrderKey("date");
$entries->setOrder("desc");
$entries->setCondition("name LIKE ?", ["%bernie%"]); // используйте подготовленные выражения! Mysqli поддерживает только ? заполнители
// или
$entries->setCondition("name LIKE :name", ["name" => "%bernie%"]); // С PDO_Mysql вы можете использовать именованные параметры
// чтобы добавить параметр к условию (до сборки 181 это нельзя было использовать с setCondition в том же списке, вы должны использовать setCondition ИЛИ addConditionParam, но не оба)
$entries->addConditionParam("city = ?", "New York", "AND"); // объединитель может быть И или ИЛИ
// используйте массивы приязок для подготовленных выражений
$entries->setCondition("city IN (?)", [["New York", "Chicago"]]);
// или
$entries->setCondition("city IN (:cities)", ["cities" => ["New York", "Chicago"]]); // именованные параметры
// при необходимости вы, конечно, можете создать пользовательский запрос
$entries->setCondition("name LIKE " . $entries->quote("%bernie%")); // убедитесь, что вы обернули переменные в кавычки!
// некоторые типы данных поддерживают прямую фильтрацию, которая может быть проверена с помощью метода 'isFilterable()' в определении поля:
if ($entries->getClass()->getFieldDefinition('имя поля напр. name или age или city')->isFilterable()) {
$entries->filterByName('Jan'); // фильтры для name='Jan'
$entries->filterByAge(18, '>='); // фильтры для age >= 18
$entries->filterByCity([['New York', 'Chicago']], 'IN (?)'); // фильтры для города из списка ('New York','Chicago')
}
foreach ($entries as $entry) {
$entry->getName();
}
// существует также сокращенный вариант
$items = DataObject\Myclassname::getList([
"offset" => $offset,
"limit" => $perPage,
"orderKey" => "date",
"order" => "desc"
]);
// сортировка по нескольким столбцам
$items = DataObject\Myclassname::getList([
"offset" => $offset,
"limit" => $perPage,
"orderKey" => ["date", "name"],
"order" => "desc"
]);
// с разными направлениями
$items = DataObject\Myclassname::getList([
"offset" => $offset,
"limit" => $perPage,
"orderKey" => ["name", "date"],
"order" => ["asc","desc"]
]);
// в случайном порядке
$items = new DataObject\PhoneProduct\Listing();
$items->setOrderKey("RAND()", false);
foreach ($items as $item) {
echo $item . "<br />"; // выведет путь к объекту
}
// с подзапросом в сортировке
$items = new DataObject\PhoneProduct\Listing();
$items->setOrderKey("(SELECT id FROM sometable GROUP BY someField)", false);
Использование подготовленных плейсхолдеров и переменных
Синтаксис аналогичен описанному здесь в Zend Framework.
<?php
use \Pimcore\Model\DataObject;
$entries = new DataObject\Myclassname\Listing();
$entries->setCondition("name LIKE ?", "%bernie%");
$entries->load();
foreach($entries as $entry) {...}
// несколько плейсхолдеров
$entries = new DataObject\Myclassname\Listing();
$entries->setCondition("name LIKE ? AND date > ?", ["%bernie%", time()]);
$entries->load();
foreach($entries as $entry) {...}
// именованные плейсхолдеры (рекомендуется)
$entries = new DataObject\Myclassname\Listing();
$entries->setCondition("name LIKE :name AND date > :date", ["name" => "%bernie%", "date" => time()]);
$entries->load();
Условия для локализованных полей
Пример ниже будет искать только значение поля name на языке EN:
<?php
$entries = new \Pimcore\Model\DataObject\Myclassname\Listing();
$entries->setLocale("en");
$entries->setCondition("name LIKE :name", ["name" => "%term%"]); // name — поле внутри контейнера localizedfield
Отключение локализованных полей в листингах
Иногда нужно исключить локализованные поля из условий и сортировки листинга. Для этого можно отключить их использование на листинге (в объектах списка локализованные поля по‑прежнему будут присутствовать, но фильтровать/сортировать по ним нельзя).
<?php
$entries = new \Pimcore\Model\DataObject\Myclassname\Listing();
$entries->setIgnoreLocalizedFields(true);
$entries->load();
Получение объектов по значению свойства
Часто требуется получить список объектов или одиночный объект, где значение свойства точно совпадает с заданным. Это удобно для поиска по внешнему ключу или при единственном условии.
$result = DataObject\ClassName::getByMyfieldname($value, ['limit' => $limit, 'offset' => $offset]);
// или варианты объектов, соответствующие значению
$result = DataObject\ClassName::getByMyfieldname($value, ['limit' => $limit, 'offset' => $offset, 'objectTypes' => [DataObject::OBJECT_TYPE_VARIANT]]);
// or for localized fields
$result = DataObject\ClassName::getByMyfieldname($value, ['locale' => $locale, 'limit' => $limit, 'offset' => $offset]);
// или варианты объектов, соответствующие значению в локализованных полях
$result = DataObject\ClassName::getByMyfieldname($value, ['locale' => $locale, 'limit' => $limit, 'offset' => $offset, 'objectTypes' => [DataObject::OBJECT_TYPE_VARIANT]]);
// или варианты объектов и объекты, соответствующие значению в локализованных полях
$result = DataObject\ClassName::getByMyfieldname($value, ['locale' => $locale, 'limit' => $limit, 'offset' => $offset, 'objectTypes' => [DataObject::OBJECT_TYPE_VARIANT, DataObject::OBJECT_TYPE_OBJECT]]);
Если лимит не задан, возвращается объект списка со всеми совпадающими объектами. Если limit = 1, возвращается первый совпавший объект напрямую (не список). Возвращаются только опубликованные объекты.
В качестве альтернативы вы можете передать во втором параметре массив опций, который будет применен к списку объектов.
$result = DataObject\ClassName::getByMyfieldname($value, ['limit' => 1,'unpublished' => true]);
Примеры
<?php
use \Pimcore\Model\DataObject;
// получить список городов Австрии
$list = DataObject\City::getByCountry("AT");
foreach ($list as $city) {
// // сделать что-нибудь с городами
$city->getZip();
...
}
// получить город по почтовому индексу
$city = DataObject\City::getByZip(5020, 1);
$city->getZip(); // // сделать что-нибудь с городом
// получить первые 10 городов в Австрии
$list = DataObject\City::getByCountry("AT", 10);
foreach ($list as $city) {
// сделать что-нибудь с городами
$city->getZip();
}
Получить список объектов / объект по локализованным полям
$list = DataObject\News::getByLocalizedfields($fieldName, $value, $locale, $limit | array('limit' => $limit, 'offset' => $offset, 'unpublished' => $unpublished));
// или
$list = DataObject\News::getByFieldName($value, $locale, $limit | array('limit' => $limit, 'offset' => $offset, 'unpublished' => $unpublished));
Примеры
<?php
use \Pimcore\Model\DataObject;
// получить список городов Австрии по локализованному полю, используя язык по умолчанию
$list = DataObject\City::getByLocalizedfields("country", "Ãsterreich");
// или
$list = DataObject\City::getByCountry("Ãsterreich");
// получить город по локализованному названию, используя язык по умолчанию
$city = DataObject\City::getByLocalizedfields("city", "Wels", null, 1);
// или
$city = DataObject\City::getByLocalizedfields("city", "Wels", null, ['limit' => 1]);
// или
$city = DataObject\City::getByCity("Wels", null, 1);
// получить первые 10 городов Австрии по локализованному полю, используя язык по умолчанию
$list = DataObject\City::getByLocalizedfields("country", "Ãsterreich", null, 10);
// или
$list = DataObject\City::getByCountry("Ãsterreich", null, 10);
// получить первые 10 городов Австрии по локализованному полю, используя язык "de"
$list = DataObject\City::getByLocalizedfields("country", "Ãsterreich", "de", 10);
// или
$list = DataObject\City::getByCountry("Ãsterreich", "de", 10);
// получить страну по локализованному названию на английском языке
$country = DataObject\Country::getByLocalizedfields("name", "Austria", "en", 1);
// или
$country = DataObject\Country::getByName("Austria", "en", 1);
Получение списка объектов, включая неопубликованные
По умолчанию списки возвращают только опубликованные объекты. Это можно изменить, установив опцию unpublished в true.
<?php
$list = \Pimcore\Model\DataObject\News::getList(["unpublished" => true]);
//or
$list = new \Pimcore\Model\DataObject\News\Listing();
$list->setUnpublished(true);
$list->load();
Иногда по умолчанию возвращаются все неопубликованные объекты даже если setUnpublished установлен в false. В данном случае, при работе на стороне администратора (например, с подключаемым модулем). Глобально поведение можно переключить следующими статическими методами:
<?php
// вернуть поведение по умолчанию — setUnpublished будет работать как обычно
\Pimcore\Model\DataObject::setHideUnpublished(true);
// принудительно возвращать все объекты, включая неопубликованные, даже если setUnpublished = false
\Pimcore\Model\DataObject::setHideUnpublished(false);
Фильтрация объектов по атрибутам из коллекций полей (fieldcollections)
Чтобы фильтровать объекты по атрибутам из fieldcollections, используйте следующий синтаксис (оба примера дают одинаковый результат):
$list = new DataObject\Collectiontest\Listing();
$list->addFieldCollection("MyCollection", "collection");
$list->addFieldCollection("MyCollection");
$list->setCondition("`MyCollection~collection`.myinput = 'hugo' AND `MyCollection`.myinput = 'testinput'");
<?php
$list = \Pimcore\Model\DataObject\Collectiontest::getList([
"fieldCollections" => [
["type" => "MyCollection", "fieldname" => "collection"],
["type" => "MyCollection"]
],
"condition" => "`MyCollection~collection`.myinput = 'hugo' AND `MyCollection`.myinput = 'testinput'"
]);
Вы можете добавить field collection в листинг, указав её тип и необязательное имя поля (fieldname) — имя поля, в котором хранится коллекция в определении класса текущего объекта. После добавления в листинг можно использовать атрибуты fieldcollection в условии. Синтаксис, как показано в примерах выше — FIELDCOLLECTIONTYPE~FIELDNAME.ATTRIBUTE_OF_FIELDCOLLECTION, или, если вы не указали имя поля — FIELDCOLLECTION.ATTRIBUTE_OF_FIELDCOLLECTION.
Пример выше вернёт объекты типа Collectiontest, у которых есть
- Fieldcollection типа
MyCollectionи значениеtestinputв атрибутеmyinput, и - Fieldcollection типа
MyCollectionв полеcollectionи значениеhugoв атрибутеmyinput
Работа с Knp\Component\Pager\Paginator
Действие контроллера
public function testAction(Request $request, \Knp\Component\Pager\PaginatorInterface $paginator): Response
{
$list = new DataObject\Simple\Listing();
$list->setOrderKey("name");
$list->setOrder("asc");
$paginator = $paginator->paginate(
$list,
$request->query->getInt('page', 1),
10
);
return $this->render('Test/Test.html.twig', [
'paginator' => $paginator,
'paginationVariables' => $paginator->getPaginationData()
]);
}
Вид
{% for item in paginator %}
<h2>{{ item.name }}</h2>
{% endfor %}
<br />
{% include 'includes/pagination.html.twig' %}
Частичный шаблон (includes/pagination.html.twig)
<nav aria-label="Pagination">
<ul class="pagination justify-content-center">
{% if(paginationVariables.previous is defined) %}
<li class="page-item">
<a class="page-link prev" href="{{ pimcore_url({'page': paginationVariables.previous}) }}" aria-label="Previous">
<span aria-hidden="true"></span>
</a>
</li>
{% endif %}
{% for page in paginationVariables.pagesInRange %}
{% if(paginationVariables.current == page) %}
<li class="page-item active" aria-current="page">
<span class="page-link">
{{ page }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item"><a class="page-link" href="{{ pimcore_url({'page': page}) }}">{{ page }}</a></li>
{% endif %}
{% endfor %}
{% if(paginationVariables.next is defined) %}
<li class="page-item">
<a class="page-link next" href="{{ pimcore_url({'page': paginationVariables.next}) }}" aria-label="Next">
<span class="flip" aria-hidden="true"></span>
</a>
</li>
{% endif %}
</ul>
</nav>
Доступ и изменение внутреннего запроса листинга
Можно получить доступ к внутреннему запросу каждого листинга и модифицировать его. Внутренний запрос основан на \Doctrine\DBAL\Query\QueryBuilder.
<?php
// Этот пример выберет все проданные автомобили.
use Doctrine\DBAL\Query\QueryBuilder;
use Pimcore\Model\DataObject\Car\Listing;
$list = new Listing();
$list->onCreateQueryBuilder(
function (QueryBuilder $queryBuilder) {
$queryBuilder->join(
'object_localized_CAR_en',
'object_query_EF_OSOI',
'onlineOrderItem',
'onlineOrderItem.product__id = object_localized_CAR_en.id'
);
}
);
Отладка SQL запроса листинга
Для отладки условий вы можете получить и вывести внутренний SQL запрос, построенный через \Doctrine\DBAL\Query\QueryBuilder:
<?php
use Doctrine\DBAL\Query\QueryBuilder;
use Pimcore\Model\DataObject\Car\Listing;
$list = new Listing();
$list->onCreateQueryBuilder(
function (QueryBuilder $queryBuilder) {
// вывести запрос
echo $queryBuilder->getSQL();
}
);
Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.