Last year, we explained what a Drupal entity was in this post titled "Drupal Entities - Part 1: What are they?". We also took a look at what entity types were and some of the types Drupal core comes with. At the end of the post we were left with two questions - Could we create our own entity type and why would we do so?
First, let us ask ourselves why we would need to create our own. As mentioned, Drupal comes with many configurations and content entities in Core. They, themselves, cover most of the needs you would have for a site. Users, pages, categories, page components, etc. You name it, there is an entity type already available to fulfill that purpose. Moreover, if Core does not have what you need, it is more than likely available as a contributed module. Take the Media entity for example, as mentioned in Part one of this post. It is a contributed module that provides a custom entity for handling various forms of media such as images and videos. As of Drupal 8.4, the media entity has been included in Core.
With these things in mind, there is little reason we would ever have to make one on our own. But just think, those contributed modules providing entity types exist for a reason. Someone felt there was a need to provide a custom solution to whatever the custom entity provides.
As you work on bigger Drupal solutions, you will discover you may be in a similar boat. The entity types in Core may not provide you with the functionality you need or it may simply not make sense for you to leverage an existing entity type for your issue. Take the Webform module as an example. As a contributed module, it provides a custom entity type that can display webforms on the frontend. Not only would it not make sense to leverage a Core entity type to fulfill this functionality, such as node, taxonomy term, user, etc. but it would not be possible since these entity types do not have this functionality.
So you can't use a core entity type to fulfill your purpose but surely there must be a contributed module out there. Given how unique one's needs could be, there might not be. But if there is, there is a chance it is not for your version of Drupal, poorly maintained, or adds too much extra functionality.
It is situations similar to this where you could decide to make your own. Well, how do we do that?
You could make it from scratch writing every line of code, creating every file on your own. Unfortunately, if you take this route, considering how complex even the simplest of entity types can be code-wise, it would be time-consuming and more prone to error. It is for this reason you'd see many people suggest using Drupal Console to generate one for you.
The drupal generate:entity:content is what you'll use to generate the content entity type. Before doing that, you'd want to create a module which you can also generate using Drupal Console's drupal generate:module.
Once you set up your module, you can begin generating your custom content entity type.
In this example, using the analogy from the previous post, we'll be creating a custom entity type called "Web Developer". This will be inside of a module called "Developer". You can place any number of content entity types within a module but it is usually good to limit it to one and name the module after the entity type. In this case, we'll be adding two, but we'll get to the second one later.
When running drupal generate:entity:content or drupal geco, you will be asked a series of questions that will aid Drupal Console in getting a base structure set up for your entity type.
The first question, "Enter the module name" refers to the module the entity type should be housed. In our case, this would be the "Developer" module. The main part of the custom entity type is the definition plugin. It is a class that will be in a file, in our case, called WebDeveloper.php inside of the /src/Entity directory of your module. The file is named after the class it contains.
Another prompt asks you to "Enter the base-path for the content entity routes". As an entity type, your content entity will have routes for various things, such as viewing an entity, adding one, a bundle listing page, etc. Drupal Console will often have defaults for these prompts in which you can just press enter without typing anything if the default satisfies your needs. The default for base-path is /admin/structure. In most cases, this will be fine so we will leave it as is. We should note the fact that this command simply generates the code we need for our custom entity type. We can go in and edit these items in code later.
The rest of the prompts should be self-explanatory enough. For our example, the prompt asking if you'd like your entity to have bundles should be marked as "yes" as our entity type will have bundles. It is "no" by default. As a side note, Bundles are actually a config entity type. We are creating two entity types if our content entity type has bundles.
After going through all the prompts, your entity type's files will be generated.
Here's an example of the process:
Once you install your module, your entity type will be ready to use. From there, you can add your bundles.
We now have our Web Developer entity type. Now try creating one for Mobile Developers and try different options to see what Drupal Console gives you.
Is that all? Maybe, maybe not. It depends on your needs. Although, if you have decided to create an entity type, to begin with, there will most likely be some customizations involved.
There are many customizations that can be made. Drupal Console just serves as a way of getting the necessary code set up quickly.
Check out this post on drupal.org that goes deeper into this subject and has many code examples.
We look forward to going over some of the cool things that can be done with content entity types in the future!