12.11. Drupal 8 Entity API. Создание кастомной сущности. Генерация сущности через Drupal Console.
Мы уже разобрались с Form API, Fields API и знаем как данные в Drupal 8 попадают в БД. Теперь давайте рассмотрим фундамент всех друпал сайтов, а именно Entity API.
Вы уже наверно заметили, что поля не существуют сами по себе, а "крепятся" к сущностям: нодам, блока, терминам таксономии, views'ам и т.д. Вы можете создавать bundle сущностей, например типы материалов, типы блоков, словари таксономии. Но что если вам нужно создать новую сущность со своими бандлами? В этом случае вам потребуется Entity API для создания новой сущности.
Я добавил весь код на github в модуль drupalbook_product, вы можете скачать модуль и добавить его к себе на сайт:
https://github.com/levmyshkin/drupalbook8
Проще всего создавать новые типы сущностей через Drupal Console, потому что потребуется выполнить всего одну команду.
https://drupalconsole.com/
Вам не придется часто создавать новые типы сущностей. Большая часть маленьких и средних проектов используют уже готовые контриб модули как основу, например Commerce для интернет-магазинов:
https://www.drupal.org/project/commerce
Если вы будете делать свой контрибный модуль, тогда возможно вам нужно будет создать новую тип сущностей, а так зачустую среди модулей друпала, можно найти уже подходящий модуль с нужным функционалом, который можно дописать или дополнить своим недостающим функционалом.
В этой статье мы разберем Entity API и создадим свой тип сущностей Product, который послужит основой для небольшого кастомного каталога или магазина. Если вы все-таки надумаете создавать кастомный магазин, то я бы настоятельно рекомендовал вам использовать Commerce, потому что это съэкономит тонны времени вам и вашим клиентам.
Когда хочешь создать новый тип сущностей встает вопрос, почему нельзя создать еще один тип материала Product и использовать его для каталога? Да, так можно сделать, для небольшого каталога товаров с выводом через Views и нехитрыми фильтрами по цене и остаткам. Но когда количество товаров будет тысячи, то менеджеру будет неудобно искать нужный товар на странице контента. Менеджер захочет прикрутить фильтры по артиклу, категории, цвету, наименованию и весь дополнительный обвес на странице
/admin/content
будет выглядеть лишним и мешать для работы с другими типами материлов Новостями, Статьями, Событиями и Страницами. Поэтому в таких ситуациях выносят отдельный тип сущностей Product со своей отдельной админкой и настройками.
Давайте приступим к созданию отдельного типа сущностей Product. Перед тем как выполнить команду на создание типа сущностей, настоятельно рекомендую создать бекап сайта, хотя бы базы данных. Потому что процесс создания типа сущности состоит частично из генерации конфигов, которые записываются в базу данных и если что-то пойдет не так и часть конфигов будет записана без файлов типа сущности в модуле, то это сломает сайт. Делаем сначала бекап.
Теперь создаем новый модуль, его также можно создать и через Drupal Console:
drupal generate:module
https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-module.html
$ vendor/bin/drupal generate:module
// Welcome to the Drupal module generator
Enter the new module name:
> Drupalbook Product
Enter the module machine name [drupalbook_product]:
>
Enter the module Path [modules/custom]:
>
Enter module description [My Awesome Module]:
> Products catalog
!>
Enter package name [Custom]:
>
Enter Drupal Core version [8.x]:
>
Do you want to generate a .module file? (yes/no) [yes]:
> no
Define module as feature (yes/no) [no]:
> no
Do you want to add a composer.json file to your module? (yes/no) [yes]:
> no
Would you like to add module dependencies? (yes/no) [no]:
> no
Do you want to generate a unit test class? (yes/no) [yes]:
> no
Do you want to generate a themeable template? (yes/no) [yes]:
> no
Do you want proceed with the operation? (yes/no) [yes]:
> yes
Generated or updated files
Generation path: /home/laptop/projects/drupalbook
1 - /modules/custom/drupalbook_product/drupalbook_product.info.yml
Generated lines: "5"
Или просто создайте модуль с файлом drupalbook_product.info.yml:
name: 'drupalbook_product'
type: module
description: 'Products catalog'
core: 8.x
package: 'Drupalbook'
Теперь мы можем сгенерировать сущность Product.
https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-entity-content.html
$ drupal generate:entity:content
$ vendor/bin/drupal generate:entity:content
// Welcome to the Drupal Content Entity generator
Enter the module name [admin_toolbar]:
> drupalbook_product
Enter the class of your new content entity [DefaultEntity]:
> DrupalbookProductEntity
Enter the machine name of your new content entity [drupalbook_product_entity]:
>
Enter the label of your new content entity [Drupalbook product entity]:
> Product
Enter the base-path for the content entity routes [/admin/structure]:
>
Do you want this (content) entity to have bundles? (yes/no) [no]:
> yes
Is your entity translatable? (yes/no) [yes]:
> yes
Is your entity revisionable? (yes/no) [yes]:
> no
// generate:entity:config
Enter the base-path for the config entity routes [/admin/structure]:
>
Generated or updated files
Generation path: /home/laptop/projects/drupalbook
1 - modules/custom/drupalbook_product/drupalbook_product.permissions.yml
2 - modules/custom/drupalbook_product/drupalbook_product.links.menu.yml
3 - modules/custom/drupalbook_product/drupalbook_product.links.task.yml
4 - modules/custom/drupalbook_product/drupalbook_product.links.action.yml
5 - modules/custom/drupalbook_product/src/DrupalbookProductEntityAccessControlHandler.php
6 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTranslationHandler.php
7 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityInterface.php
8 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntity.php
9 - modules/custom/drupalbook_product/src/DrupalbookProductEntityHtmlRouteProvider.php
10 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityViewsData.php
11 - modules/custom/drupalbook_product/src/DrupalbookProductEntityListBuilder.php
12 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntitySettingsForm.php
13 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityForm.php
14 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityDeleteForm.php
15 - modules/custom/drupalbook_product/drupalbook_product_entity.page.inc
16 - modules/custom/drupalbook_product/templates/drupalbook_product_entity.html.twig
17 - modules/custom/drupalbook_product/templates//drupalbook-product-entity-content-add-list.html.twig
18 - modules/custom/drupalbook_product/drupalbook_product.module
19 - modules/custom/drupalbook_product/drupalbook_product.module
20 - modules/custom/drupalbook_product/drupalbook_product.module
21 - modules/custom/drupalbook_product/config/schema/drupalbook_product_entity_type.schema.yml
22 - modules/custom/drupalbook_product/drupalbook_product.links.menu.yml
23 - modules/custom/drupalbook_product/drupalbook_product.links.action.yml
24 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityTypeInterface.php
25 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityType.php
26 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTypeHtmlRouteProvider.php
27 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityTypeForm.php
28 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityTypeDeleteForm.php
29 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTypeListBuilder.php
Generated lines: "1060"
Теперь когда модуль сгенерирован, то вы можете его включить, чтобы новый тип сущности появился на сайте:
При генерации сущности Drupal Console спрашивает какой должен быть тип сущности.
Enter the class of your new content entity [DefaultEntity]:
Имя PHP класса для нашей сущности, лучше всего на конце имени добавить Entity.
Enter the machine name of your new content entity [drupalbook_product_entity]:
Машинное имя класса будет предложено на основе имени класса, если нажать Enter, то будет использоваться предложенное имя.
Enter the base-path for the content entity routes [/admin/structure]:
У сущностей ващего типа будет своя страница для CRUD операций:
Внешний вид страницы с продуктами, довольно примитивный, но его можно будет улучшить в будущем или создать через Views:
Чтобы создать новую сущность, сначала нужно создать bundle типа сущности Product type. Мы выбрали bundable сущность:
Do you want this (content) entity to have bundles? (yes/no):
Поэтому создаем новый тип продуктов. Это нужно будет нам для создания разных полей Вес, Размер, Цвет и другие дополнительные характеристики. Например у мониторов будет диагональ экранов, а у обуви Размер обуви.
Давайте создадим новый Product type - Clothes:
Теперь у нашего нового типа продуктов можно настраивать поля:
Нам точно понадобится поле цены как минимум.
Давайте создадим пару продуктов и заглянем в базу данных. У нас есть таблица drupalbook_product_entity в ней хранятся UUID наших продуктов:
Также есть еще одна таблица drupalbook_product_entity_field_data, в ней храняться Properties. Это особенные поля сущностей, которые лежат хранятся прямо в таблицы, потому что эти поля такие как Name (Entity label, например это Title у ноды), не будут менятся в зависимости от ревизии.
Если вы добавляете поля, то будут создаваться две таблицы для каждого поля, потому что мы выбрали использование ривизий:
Is your entity revisionable? (yes/no) [yes]
Думаю теперь вам понятно как создавать новый типы сущностей. В следующих статьях мы расширим возможности нашего кастомного каталога/магазина.
Я добавил весь код на github в модуль drupalbook_product, вы можете скачать модуль и добавить его к себе на сайт:
https://github.com/levmyshkin/drupalbook8