Drupal 8 Entity Series - Part Two -- Creating Entity Boilerplate Code
In part one of the Drupal 8 Entity series, I described the origins and definition of the Entity concept, as well as many of the differences between entities in Drupal 7 and Drupal 8. In this article I will describe how to create a content entity type and some of the basic features that you get from a relatively simple initial process.
Creating Custom Entity Types in Drupal 8
As you know if you've developed custom entities for Drupal 7, it required a lot of research, poking around for documentation, and looking at code that came before us.
There are tools available to work in conjunction to make the development of Drupal modules, and Entity Types easier for Drupal 8. In this article we'll step through the process of creating our own Entity Type, "Cars" which will include integration with the Drupal Admin UI, where one can manage settings, manage fields, manage form display, and then manage display modes. In addition we will have created an entity listing, and add/edit/delete forms.
Drupal.org provides some documentation on how to create your own Entity programmatically, but we hope to show you there is a new, powerful way to start Entity development in Drupal 8.
Drupal 8 module development is quite a bit different, and conceptually sophisticated, than Drupal 7 module development. The integration of Symfony, and modern OO practices such as namepaces, dependency injection, services, containers, and factories for object instantiation, makes the conceptual learning for the initial code framework required for a module and entity type creation and management seem a bit steep in for some of us Drupal 7 developers.
Never fear, the Drupal community is near.
Drupal Console
Individuals in the Drupal community has come through and produced a great new tool to use with Drupal 8, Drupal Console. Visit their page and thank them.
Drupal Console is " is a suite of tools that you run on a command line interface (CLI) to generate boilerplate code and interact with a Drupal 8 installation." Drupal Console creates this module and entity boilerplate code and object oriented framework for you, with just a few keystrokes. This takes the burden of "how" to integrate in the Drupal entity system off the developer initially, and allow them to focus on the specific or custom logic that makes this entity different from the rest. Drupal Console creates a code template for you, all you need to know from there is where to put your additions and logic. Getting started with Drupal 8 entity development is relatively easy, as I hope to show you.
All the new concepts of Drupal 8, once understood, make for a more mature, organized, and flexible development experience. Drupal Console eases the pain of learning by providing simple, useful examples that you can immediately customize.
Install Drupal Console
We'll copy from drupalconsole.com, because this explains it directly:
# Run this in your terminal to get the latest Console version: curl -LSs http://drupalconsole.com/installer | php # Or if you don't have curl: php -r "readfile('http://drupalconsole.com/installer');" | php # You can place this file anywhere you wish. # If you put it in your PATH, you can access it globally. # For example: move console.phar and rename it, 'drupal': mv console.phar /usr/local/bin/drupal # Show all available Drupal Console commands. drupal # Copy configuration files to home user directory drupal init
Generate a module
First you must generate the minimum required code, files, and file structure to have a Drupal 8 module. The generate commands will ask series of questions, with sane defaults in brackets. To do this, use drupal console:
# Generate a module. drupal generate:module Welcome to the Drupal module generator Enter the new module name: Cars Enter the module machine name [cars]: cars Enter the module Path [/modules/custom]: Enter module description [My Awesome Module]: Cars Entity Type and Cars related fields Enter package name [Other]: Enter Drupal Core version [8.x]: Define module as feature [no]? Do you want to add a composer.json file to your module [no]? yes Would you like to add module dependencies [no]? Do you confirm generation [yes]? yes Generated or updated files Site path: /Applications/MAMP/htdocs/d8rc1 1 - modules/custom/cars/cars.info.yml 2 - modules/custom/cars/cars.module 3 - modules/custom/cars/composer.json
So very cool, I am asked a series of simple questions, and I type the answers, and voila, I have a module that has the necessary files to be installed on a Drupal 8 site. It as yet has no functionality, but you will see it on the Extend (install modules) page, and you can enable it. (but wait until the next step to do so). I can see what files where created and where, and take a peak at the basic boilerplate code. I'll leave the explanation the files are, what they do, for another article, we want an Entity here!
Create our Entity Type
Now to create our entity, on the command line, inside our drupal 8 installation, type:
drupal generate:entity:content --module cars
This command will ask the basic questions necessary to build a entity type Cars, and create and place the necessary files in the previously created module Cars.
- Give the Entity Class Name
- Give the Entity Machine Name
- Give the Entity label
Answer thee these question three, and Drupal Console will create module code for an Entity Type!
commands.generate.entity.questions.entity-class [DefaultEntity]: Cars commands.generate.entity.questions.entity-name [cars]: cars commands.generate.entity.questions.label [Cars]: Generated or updated files Site path: /Applications/MAMP/htdocs/d8rc1 1 - modules/custom/cars/cars.routing.yml 2 - modules/custom/cars/cars.permissions.yml 3 - modules/custom/cars/cars.links.menu.yml 4 - modules/custom/cars/cars.links.task.yml 5 - modules/custom/cars/cars.links.action.yml 6 - modules/custom/cars/src/CarsInterface.php 7 - modules/custom/cars/src/CarsAccessControlHandler.php 8 - modules/custom/cars/src/Entity/Cars.php 9 - modules/custom/cars/src/Entity/CarsViewsData.php 10 - modules/custom/cars/src/CarsListBuilder.php 11 - modules/custom/cars/src/Entity/Form/CarsSettingsForm.php 12 - modules/custom/cars/src/Entity/Form/CarsForm.php 13 - modules/custom/cars/src/Entity/Form/CarsDeleteForm.php 14 - modules/custom/cars/cars.page.inc 15 - modules/custom/cars/templates/cars.html.twig
Ok, very cool, its telling me about it generated a lot of files, containing the necessary Drupal 8 classes, generated from the questions I answered.....so without opening a text editor, I've got the basic files and code in the proper directory structure, to have a Car entity type!
Now go to the extend admin page at <yoursite>/admin/modules and enable your new module.
What all do we have now?
Go to the Admin Configuration listings (/admin/index), and lo and behold, there's a group "Cars" with two menu items:
- Cars settings
- Configure Cars permissions.
Entity settings
Clicking on "Cars settings" takes you to a config page that reveals some familiar things, a page with 4 tabs (/admin/structure/cars). New entity type settings can be configured at "/admin/structure/[entity-machine-name]"
- Settings
- Manage fields
- Manage form display
- Manage Display
Manage Fields
You can add fields, just as you did in Drupal 7. I've created a "Description" field, which I configured to be a Formatted, Long Text, with summary field. This is done via the admin UI in the normal fashion one would add a field in D7.
Manage Form Display
What's this? What are these two other fields, Name and Authored By? In Drupal 7 these may be some typical properties that you would add to a Entity type. This is similar to the "Title" property of Nodes. In Drupal 7 entities, these would be properties, and would not have any "out-of-the-box" edit form field widget and field display options. It takes more than a bit of work and Display Suite to make Drupal 7 Entity properties even close to as flexible as a Field from a UI perspective.
In Drupal 8, there are 2 default field variants, Base Fields, and Configurable Fields. Base fields are fields that are required for every entity, even different entities of different bundles. This corresponds to the behavior of Drupal 7 Entity properties. Now these required properties are full Drupal Field API fields and customizable via field widget and field formatter plugins.
Entity Property in Drupal 7 = Base Field in Drupal 8 for Content Entities
Field in Drupal 7 = Configurable Field in Drupal 8 for Content Entities
and for all intents and purposes in Drupal 8
Base Field = Configurable Field = Field
Notice the two the two fields "Name", and "Authored by". These are the two Base Fields generated by Drupal Console. The widget and widget options are configurable, just as all fields in D7 were. In addtion you can see in the screenshot below the Configurable Field (same as standard Drupal 7 Field), "Description" which I created earlier.
There are other Base Fields attached to the Car entity, generated by Drupal Console, but defined not to show to be configured on the manage fields or manage form display pages, and their inclusion on the add/edit form, or the display is handled conditionally in the background. These include id, uuid, language, created, and changed. Values for these fields are generally handled automatically, but can be displayed in Views or their values retrieved via the Entity API. More on how this is done and can be manipulated in future articles.
Manage Display
The Manage display screen, showing both the 2 Base Fields, and one Configurable Field, all with field formatter options.
Permissions
Clicking on the Cars permissions link, takes you to the user permissions page, and straight to permissions settings for adminstration rights and each CRUD operation for the newly created Entity type.
What else do we get "for free"?
Entity listing and adding new entities
You'll notice there's a new menu item in the Tools menu.
In my example the path is "/admin/cars" (same style as admin/content). The "cars" url component is based on my Entity type machine name. What's this, an "Cars content" listing? A mechanism for displaying a list of all Cars is provided, as well as a button to create new Cars.
From here I can see any Cars entities, or add a new Car. (/admin/cars/add). So on top of everything, we get a Cars listing, add, edit, and delete forms
Total integration, 5 minutes, no code actually written by me yet. Say it together, "Awesome-sauce". We created a fully functional Drupal 8 Entity type in 5 minutes! I can add fields, manage the display, view Cars, edit Cars, delete Cars, and create Views of Cars, all from the code generated by Drupal Console. With a little know-how, creating a custom Drupal 8 Entity type is almost as easy as adding a new Content Type!
This Entity type will have full Entity API support, including support for entity metadata wrappers and Views integration.
In Part Three I will discuss what each of the generated files are and contain in some detail, before moving on to customizing the Car Entity type further, by adding field types, fields, revisions, translation, and more.