Розробка користувальницьких типів контенту Drupal
Типи контенту в Drupal — це сущності з набором полів. Стандартні Article та Page замінюються або доповнюються типами під конкретну задачу: Новина, Кейс, Вакансія, Продукт. Налаштовуються в UI, конфігурація експортується в YAML і коммітиться в git.
Створення через UI
Шлях: /admin/structure/types/add. Задаємо ім'я (Label) та машинне ім'я (slug). Drupal створює тип з базовими полями: Title, Body, Published.
Після створення — додаємо користувальницькі поля: /admin/structure/types/manage/{type}/fields/add-field.
Експорт конфігурації в YAML
Після налаштування в UI:
drush config:export
У config/sync/ появляться файли:
node.type.news.yml # сам тип
field.storage.node.field_subtitle.yml # хранилище поля
field.field.node.news.field_subtitle.yml # поле для конкретного типу
core.entity_form_display.node.news.default.yml # форма редагування
core.entity_view_display.node.news.default.yml # вид відображення
core.entity_view_display.node.news.teaser.yml # вид teaser
Приклад node.type.news.yml:
langcode: en
status: true
dependencies: {}
name: Новини
type: news
description: 'Новини компанії'
help: ''
new_revision: true
preview_mode: 1
display_submitted: false
Конфігурація поля
# field.field.node.news.field_subtitle.yml
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_subtitle
- node.type.news
id: node.news.field_subtitle
field_name: field_subtitle
entity_type: node
bundle: news
label: 'Підзаголовок'
description: 'Короткий анонс для списків та карток'
required: false
translatable: true
default_value: []
settings: {}
field_type: string
Програмне створення типу (через install-хук)
Якщо тип створюється модулем, а не вручну:
// my_module.install
function my_module_install(): void {
// Створюємо тип контенту
$node_type = \Drupal\node\Entity\NodeType::create([
'type' => 'vacancy',
'name' => 'Вакансія',
'description' => 'Відкриті вакансії компанії',
'display_submitted' => FALSE,
'new_revision' => TRUE,
]);
$node_type->save();
// Поле "Місто"
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_city',
'entity_type' => 'node',
'type' => 'string',
'cardinality' => 1,
]);
$field_storage->save();
\Drupal\field\Entity\FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'vacancy',
'label' => 'Місто',
'required' => TRUE,
'settings' => ['max_length' => 100],
])->save();
// Поле "Зарплатна вилка" — decimal
$salary_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_salary_min',
'entity_type' => 'node',
'type' => 'decimal',
'settings' => ['precision' => 10, 'scale' => 0],
]);
$salary_storage->save();
\Drupal\field\Entity\FieldConfig::create([
'field_storage' => $salary_storage,
'bundle' => 'vacancy',
'label' => 'Зарплата від',
])->save();
// Entity reference на таксономію "Напрямок"
$ref_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_direction',
'entity_type' => 'node',
'type' => 'entity_reference',
'settings' => ['target_type' => 'taxonomy_term'],
'cardinality' => \Drupal\Core\Field\FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
]);
$ref_storage->save();
\Drupal\field\Entity\FieldConfig::create([
'field_storage' => $ref_storage,
'bundle' => 'vacancy',
'label' => 'Напрямок',
'settings' => [
'handler' => 'default:taxonomy_term',
'handler_settings' => [
'target_bundles' => ['directions' => 'directions'],
'auto_create' => FALSE,
],
],
])->save();
// Налаштування форм відображення
\Drupal\Core\Entity\Entity\EntityFormDisplay::load('node.vacancy.default')
->setComponent('field_city', [
'type' => 'string_textfield',
'weight' => 10,
'settings' => ['size' => 60],
])
->setComponent('field_direction', [
'type' => 'options_buttons',
'weight' => 20,
])
->save();
}
Типичні типи полів
| Ситуація | Тип поля |
|---|---|
| Короткий текст | string |
| Довгий текст / HTML | text_long або text_with_summary |
| Число цілісне | integer |
| Число дробове | decimal або float |
| Дата | datetime |
| Ссилка на іншу сущість | entity_reference |
| Зображення | image |
| Файл | file |
| Булево | boolean |
| Список (select) | list_string або list_integer |
email |
|
| Ссилка (URL) | link |
Пов'язані типи та reference поля
Типічна структура: Кейс → Клієнт (entity reference), Кейс → Послуги (entity reference multiple).
# field.storage.node.field_client.yml
field_name: field_client
entity_type: node
type: entity_reference
cardinality: 1
settings:
target_type: node
# field.field.node.case.field_client.yml
field_name: field_client
bundle: case
label: 'Клієнт'
settings:
handler: 'default:node'
handler_settings:
target_bundles:
client: client
sort:
field: title
direction: ASC
auto_create: false
Ревізії
Для типів, де потрібна історія змін, включаємо new_revision: true. Робота з ревізіями:
// Завантажити всі ревізії ноди
$storage = \Drupal::entityTypeManager()->getStorage('node');
$revision_ids = $storage->revisionIds($node);
$revisions = array_map(fn($rid) => $storage->loadRevision($rid), $revision_ids);
// Откатити до ревізії
$node->setNewRevision(FALSE);
$node = $storage->loadRevision($target_revision_id);
$node->isDefaultRevision(TRUE);
$node->save();
Терміни
Один тип контенту з полями через UI + експорт конфігурації: полдня. Кілька типів з зв'язками, налаштування форм відображення, Views: 1–2 дні.







