Сущности: загрузка и поля
Материалы, пользователи, термины таксономии, файлы — всё это сущности. У них общий способ загрузки, чтения полей и сохранения. Освоив его на материалах, вы умеете работать и со всем остальным. Отдельных файлов для этого создавать не нужно: код пишут там, где нужны данные, — в контроллере, форме, блоке или хуке.
Хранилище
Все операции идут через хранилище сущностей нужного типа. В контроллере его получают так:
// web/modules/custom/blog/src/Controller/BlogController.php
public function first(): array
{
$storage = $this->entityTypeManager()->getStorage('node');
$node = $storage->load(1);
return ['#markup' => $node->label()];
}getStorage('node') возвращает хранилище материалов, load(1) — материал с номером 1, label() — его заголовок. Если привязать метод к маршруту, страница покажет заголовок первой статьи. Когда материала с таким номером нет, load() возвращает NULL.
В хуках и сервисах хранилище получают через сервис: \Drupal::entityTypeManager()->getStorage('node').
Несколько сущностей
// web/modules/custom/blog/src/Controller/BlogController.php
$nodes = $storage->loadMultiple([1, 2, 3]);
$articles = $storage->loadByProperties(['type' => 'article', 'status' => 1]);Оба метода возвращают массив, где ключ — номер сущности. loadByProperties() ищет по точному совпадению значений: здесь — все опубликованные статьи.
Общие методы
| Метод | Что возвращает |
|---|---|
id() | Номер |
label() | Заголовок |
bundle() | Разновидность: у материала — тип, article |
getEntityTypeId() | Тип сущности: node |
toUrl()->toString() | Адрес страницы |
isPublished() | Опубликован ли материал |
getCreatedTime() | Время создания, число секунд |
getOwner() | Автор — сущность пользователя |
Чтение полей
// web/modules/custom/blog/src/Controller/BlogController.php
$body = $node->get('body')->value;
$summary = $node->get('body')->summary;get('имя_поля') возвращает объект поля, а само значение лежит в его свойстве. У простых полей — текста, чисел, дат — это value. Имена полей — машинные: body, field_image, field_tags.
Перед чтением поля, которого может не быть у типа материала, проверяют: $node->hasField('field_image').
Поля со ссылками
Метки и картинка — ссылки на другие сущности:
// web/modules/custom/blog/src/Controller/BlogController.php
$imageId = $node->get('field_image')->target_id;
$image = $node->get('field_image')->entity;
$imageUrl = $image?->createFileUrl();target_id — номер связанной сущности, entity — сама сущность, уже загруженная. Если картинка не задана, entity равно NULL.
Несколько значений
Поле с метками хранит несколько значений. Их перебирают циклом:
// web/modules/custom/blog/src/Controller/BlogController.php
$names = [];
foreach ($node->get('field_tags')->referencedEntities() as $term) {
$names[] = $term->label();
}В $names окажутся названия всех меток статьи. Запись ->value или ->entity без цикла возвращает только первое значение.
Изменение
// web/modules/custom/blog/src/Controller/BlogController.php
$node->set('title', 'Новый заголовок');
$node->set('body', ['value' => 'Новый текст.', 'format' => 'basic_html']);
$node->save();set() меняет значение в объекте, а в базу оно попадает только после save(). У текстового поля два свойства: сам текст и формат, которым его обрабатывать при выводе.
Другие сущности
// web/modules/custom/blog/src/Controller/BlogController.php
$user = $this->entityTypeManager()->getStorage('user')->load(1);
$email = $user->getEmail();
$terms = $this->entityTypeManager()
->getStorage('taxonomy_term')
->loadByProperties(['vid' => 'tags']);Меняется только имя типа сущности. vid — словарь таксономии.
Частая ошибка
load() возвращает NULL, если сущности нет, и вызов $node->label() завершится ошибкой «Call to a member function on null». Перед использованием проверяйте результат. А если номер приходит из адреса, пусть материал загружает маршрут — параметр {node} из урока о параметрах сам вернёт 404 для несуществующего номера.