12.11. Drupal 8 Entity API. Создание кастомной сущности. Генерация сущности через Drupal Console.

Главные вкладки

levmyshkin 7 августа 2019 в 19:48

Мы уже разобрались с 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

Атрибуция

Абраменко Иван

Автор