This past week/weekend, I went through the process of defining a D8 content entity type with bundles (because I'm working on the d8 update of my programming with Drupal book), and with a UI that allows you to do CRUD on both the entity objects and bundles.

Keep in mind that I'm kind of an outsider to entity defining in D8 -- I haven't been very involved in building the existing core system (which I think gradually evolved) or the existing core entities.

I used the existing entities as a model... but it took me hours of debugging to get it all working, and the code and routes I ended up with were still not all that great at the end of it all. Maybe there were things I didn't understand (where we need better documentation), and maybe it's just that the DX needs improvement?

Anyway, defining a UI for entities seems very complex. Between the main entity and the config entity for the bundles, this involved defining:

  • 8 routes with placeholders
  • Various menu links, action links, and task links
  • A theme hook, Twig template, and preprocess function for displaying the content entity
  • 9 classes and interfaces for the entities, their forms, and the config list controller
  • A config schema for the bundle entity
  • A few methods in a Controller outside the entity space
  • - A URI callback function [no longer necessary]
  • A permission in hook_permission()
  • Views integration for the content entity, assuming you want to use Views to make an admin page similar to admin/content (I didn't actually yet even do that); then you'd want to also export your view as config.
  • And I just found out that if I am using SQL storage and want it to have decent indexes, I also need to define a storage controller class; see #2326949: Move entity-type-specific schema information from the storage class to a schema handler

This process seems overly complicated, and part of the problem was that I pretty much had to do all of the above steps before I could test anything in the UI.

Here are some things that occurred to me during this process, that I thought could be improved:

Comments

jhodgdon’s picture

Berdir’s picture

Some first answers.

a) Sure, that would be great. Config schema is fairly new. config translation UI's afaik actually use it to some degree. Problem is simply that nobody wrote this, like many other things.

b) Not sure what you exactly did in your content entity form, but you can use widgets for the form elements there, not for everything yet but we are working on this. See https://github.com/christophegalli/content_entity_example/blob/cee_devel... for an example and https://github.com/christophegalli/content_entity_example/blob/cee_devel.... There is an issue to have a default for save() too: #2312133: Make EntityForm::save() save the entity

For the language thing, there's also an issue to make that a widget: #2230637: Create a Language field widget and the related formatter. Was attempted in #2226493: Apply formatters and widgets to Node base fields but it is tricky because while it is very similar, it is slightly different in many places, see that issue.

c) Yes, I've been wondering about a default delete confirm form too. Problem as with some of your other points is that in core, those forms very often slightly vary in their behavior and language (writing generic, good confirmation messages is harder than you'd think, starts with lower/uppercase/plural labels and wording), sometimes for good, sometimes for no reason.

d... (no d) e) Yes, the other issue you found from Crell is about this. Again, if you look at core, most entity types have small differences, partially for historical reasons. Generating something by default would make it harder to apply those small variations, because they would have to be route alterations. Another point that tim mentioned is that it will possibly be harder to look at an existing module and understand what it does. Right now, the routing.yml is basically the summary of all the UI's that a module provides. I *think* that I would prefer a one-time genreation of all the needed routes with comments/explanations over magic at this point.

f) Yes. I've been working on standardizing things like that for a while. Related issues:
- #2023571: Support preprocessing in EntityViewBuilder
- #2301245: Entity system invokes non-existing theme hooks: "Theme hook $entity_type_id not found."
- #2270883: Automatically add theme hook suggestions for all entity types

Again, one problem was slight differences in the existing templates (example, node template used node_url, others used url and so on. This example actually got fixed).

Not sure if you ever did this in 7.x (without entity.module, this is an area where it still has some improvements on 8.x), but it was not any better there.

g) Again, same (boring) story, reality is that there are almost always small differences in the dozen or so config list builders in core, AFAIK it did include the label at some point, but the result was that there were more subclasses that had to alter it (which is actually more complicated code) than those that could just use it. And yet another subclass wouldn't be nice either, but was discussed before.

jhodgdon’s picture

Regarding things being slightly different between entity to entity on some of the classes... I do realize that.... But at least if the base classes had more methods on them so that they weren't abstract, and defined some default behavior, they would function without the need to subclass. Then you could at least get going with minimal work and refine/subclass later on if necessary.

As it is now, I really couldn't even test *anything* in my entity definition module or even enable it until all of the classes, routes, etc. that I listed in the issue summary had been created, and then I had to debug everything (all very interconnected) at once, which was quite a lot of code and I had a lot of bugs due to there being a lot of stuff I didn't know and that wasn't obvious, even after looking at the examples. I mean, you want to make a minimal working set and then build on it, and it's not clear looking at the examples what is essential for my entity vs. specific stuff for those specific entities, and saying you need to look at all the examples at once and compare and contrast (which is basically what I ended up having to do) is ... a lot of work. We're talking all those classes for all those entities, and for most of them, the classes are scattered around between Entity, Form, Controller, and the base module namespace, not even collected all in one place, making it even harder to figure out what is going on... Really it's a huge mess and the examples in core are rather inscrutable.

Regarding the routes... Maybe we could somehow have a shorthand that would get all the permissions, placeholders, etc. right? Something like:

my.route.name:
_entity_route: myentity
_route_type: edit

Because I *still* don't know how to get the routes working right. I ended up not even using the entity permissions in the requirements section of the routes, just a generic "administer my entity" permission instead, because I couldn't get it working immediately and wanted to move on to debugging other things. Way more painful than it needed to be... I am still not sure of the interaction between entity loading, entity classes, entity annotation, permissions, and routes... but they're all interconnected in ways that are not obvious to me, even now.

Oh and no, in 7.x I always used the Entity API module. It was certainly a mess without in 7.x as well. I'm not saying necessarily that it's worse, but in 7.x there wasn't the distinction between config and content entities so at least you only had to learn about one way to do things. In 8.x, what was one convoluted section in the 7.x version of the book (even with Entity API) is now two convoluted sections of about the same length as the 8.x section. It just doesn't seem to be better.

jhodgdon’s picture

Issue summary: View changes

timplunkett commented in IRC:

...if subclassing abstract classes is a problem for you, it's not something i can help with

I just want to say that each individual class wasn't really a problem. It was just the sheer number of classes, routes, etc. that needed to be defined, most of which had to be all created at once, with no typos, before anything could be tested, that made the whole process tedious.

That and a few, as far as I can tell, undocumented gotchas. And the routing stuff for entities is also a bit opaque...

Anyway, we don't have to fix this... they are just suggestions that I think could make the process easier to do by increments. As webchick said to me in IRC yesterday, the thought was that the plugin/entity system in D8 was supposed to make things easier. I think it has for generic plugins, like blocks, which are all on one class... but I don't see that the process is any easier for entities than it was in D7. It is still rather convoluted and involved -- as noted in the issue summary, you have to edit or create at least 16 different files, in order to define 1 content entity type with bundles. [I just added one: I had forgotten about the config entity schema.]

jhodgdon’s picture

Oh, and I didn't even get to the Views integration, which I would need/want in order to make the equivalent of admin/content for this entity.

jhodgdon’s picture

Title: Improve DX of entity defining » Improve DX of entity defining (if you want a UI)
Issue summary: View changes

Tim pointed out to me in IRC that the craziness here is only true if you want a UI. If you do not need a UI, then you can just define your two entity classes and you are done.

I'm updating the issue summary.

catch’s picture

xjm’s picture

Title: Improve DX of entity defining (if you want a UI) » [meta] Improve DX of entity defining (if you want a UI)
Issue tags: +DX (Developer Experience)
Related issues: +#1740492: Implement a default entity views data handler
jhodgdon’s picture

Berdir helped me figure out where I went wrong in a couple of places, and things are *slightly* simpler. Updating summary and adding new related issue.

alexweber’s picture

Just stumbled upon this... as someone who's been watching from a distance and playing with the new APIs every couple weeks or so I gotta echo @jhodgdon here on this one!

I'm very familiar with D7 Entity API and pretty familiar with all of the D8 plugins/service architecture and I gotta say that I've spent multiple hours at a time on multiple occasions referring to core example and docs and trying to get some sample content entities going and boy, is it an adventure!

It's actually super elegant once you wrap your head around it but the end result is kinda like D7 where you have piles of boilerplate model entity code that you are copying and pasting and renaming for each new project kinda deal, which just sucks.

All of that said, I think scaffolding will make none of this matter anymore: https://www.drupal.org/project/console :)

effulgentsia’s picture

Do folks here want to share any thoughts about #2326949: Move entity-type-specific schema information from the storage class to a schema handler (which proposes to add yet one more class) on that issue? Thanks.

jhodgdon’s picture

Gracious. Commented on the other issue, and adding Storage to the summary. Also reformatted the summary for easier scanning.

jhodgdon’s picture

Issue summary: View changes

typo

andyceo’s picture

xjm’s picture

Version: 8.0.x-dev » 8.2.x-dev
Issue tags: -beta target

This issue was marked as a beta target for the 8.0.x beta, but is not applicable as an 8.1.x beta target, so untagging.

This could potentially be implemented in a minor with BC, so moving to 8.2.x.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joachim’s picture

I'd like to look at reducing the amount of boilerplate for custom entity types -- is this the best issue to focus things on, or should I start a new Plan issue, since I think this isn't necessarily about providing a UI?

Now I've done the bulk of custom entity type generation in Module Builder, I think I have a pretty good idea of some areas where things could be improved.

Collecting some related issues:

- #2809177: Introduce entity permission providers
- #2949964: Add an EntityOwnerTrait to standardize the base field needed by EntityOwnerInterface
- #1798540: Add link to add a new entity in an empty entity list controller table
- #2976861: add an entity Links handler, to provide menu links/tasks/actions for entity types

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

AaronMcHale’s picture

Status: Active » Closed (outdated)
Related issues: +#2095603: [meta] Complete Entity Field API

Closing in favour of #2095603: [meta] Complete Entity Field API as it is tracking more issues and has the same purpose.