Closed (fixed)
Project:
Examples for Developers
Version:
8.x-1.x-dev
Component:
Entity Example
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Reporter:
Created:
18 Mar 2014 at 18:45 UTC
Updated:
13 Sep 2014 at 20:50 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
cgalli commentedComment #3
berdir@cgalli: looks like you managed to create windows file endings again :)
Attaching the same patch, just with unix line endings, converted with dos2unix.
Comment #4
mile23Ossum, thanks. :-)
Comment #5
mile23Comment #6
berdirPermissions are usually readable strings, like administer content_entity_example entity.
No need to repeat these methods, they exist in the parent. You should however extend from ContentEntityInterface.
You only want to add method for your own fields, when useful.
If you actually want to support translations, you should provide a per-translation table. See EntityTestMul for an example. See also the corresponding table definitions. Most of your fields will move to the _field_data table.
I would name this just "id". Then you also don't need to override the id() method (will not be necessary anymore after #2182239: Improve ContentEntityBase::id() for better DX anyway)
The definitions are IMHO betterreadable with an empty line between them.
Conflicting length definitions, you only need one of those (max_length easier).
You don't have bundles, so I would leave this out.
I think it's easier to have an example with bundles and one with, to see the difference. So let's add one without bundles first.
Your entity (the interface) should implement EntityOwnerInterface in this case, then you'll need to implement the corresponding methods (setOwnerId() and so on). Other modules can then rely on that (comment does and entity_reference for example).
WE should also add changed and created fields, there are special field types for that that just work, see Node.
Not sure how useful this really is?
Maybe if you use a different field type, like a text field with a text that has a format?
I would also give it a real name, maybe "description"?
Should use \Drupal:l() and the route name instead of the path.
Comment #7
cgalli commentedNew patch included. Yes, I passed it through dos2unix :-)
1) Changed permissions naming. 2 questions remaining:
- The edit and delete permissions work for the node, but the operations column in the list view is not affected.
- The administer permission is not enough to make the admin menus accessible. What am I missing?
2) Removed. The interface is empty but still necessary I believe.
3) Removed translation. Maybe we can implement it in the 'extended' example
4) Renamed to 'id'. I had named it differently to demonstrate the ability of twig to call the id function (as opposed to using the id property)
5) Fixed
6) Removed
7) 'created' and 'changed' fields added. Even in schema.
EntityOwnerInterface implemented. Question: the functions seem to be abstract. Where is this defined?
8) Removed the additional field. It does not add anything that the 'name' field does not already demonstrate.
9) Implemented
Comment #8
cgalli commentedHere comes the interdiff.
Comment #9
berdirYou can add EntityChangedInterface to the list now.
Hm, having a langcode is very common for content entities, even if they're not translatable. Fine, though.
Why this rename? I actually liked user_id more :)
Comment #10
mile23It'd be great to have some explanation of each of these interfaces, and what they deliver to the implementation.
+1 on langcode. Seems like a best practice, and best practices are what we're here to explain.
+1 on user_id as well. Descriptive and readable is better.
There was some discussion in email about what to name the entities. I like that the config entity example has 'Robot,' which is distinct and understandable. 'content_entity_example' is the same name as the module, leading to confusion. Let's dream up something that we're modeling here, so that we can then explain how our model maps into an entity implementation.
Comment #11
berdirAbout naming, I agree that something specific would be nicer, the downside is that it then violates the module namespace. But maybe we can solve that by adding a comment on the entity class and state that real entities must live within the namespace of out their module?
Because we'll eventually need 3 different entity types, the idea is to have this as starting point for simple content entities and a more complex one with translatable storage, revisions, bundles (which will need a config entity) and so on. I thought about relying on the config_entity_example module for that, but robots isn't really a good example for that ;)
Comment #12
mile23Well my point is that there's presumably a design phase where you discover that you need to make an entity in order to represent something. So, for instance, an address book where you have to represent people and their addresses. This gives the reader something to hang it all on, rather than simply 'this is an example of a content_entity_bundle_thingie_example_no_clue_why_i_need_it.'
The module namespace isn't so relevant as the class namespace.
Drupal\content_entity_example\Entity\Robottells the whole story, and is how sane people should name things anyway. :-)Comment #13
berdirIn an actual module, it would still be required to use content_entity_example_robot as the entity type ID. (Just like all other plugins, machine names, routes, ...) Namespaces don't solve that problem. But yes, naming the class like that is perfectly fine.
Comment #14
mile23Entity type ID is an arbitrary string, right? So 'content_entity_example.robot' or however you want?
Comment #15
berdirNo, only lowercase and _ is allowed, and there will be a length limit, although it's not exactly clear yet how long that should be but likely 32 or 50 characters. That string is used for table names for fieldable entities, needs to match variable names so that upcasting works and so on.
We just tried to make that module prefix official and standardized, but it has too many dependencies, see #1862600: Entity type names/IDs are not properly namespaced by owner (e.g., taxonomy.term vs. taxonomy_term).
Comment #16
cgalli commentedI like the the idea of putting up some real-life example like an address book or similar. We could do 'person' as the minimal entity and expand into a specific group of people (drupalistas?) as a bundle with all the gimmicks (tranlations, revisions, presentation with twig etc).
Functional comments and tests will be added as well.
As far as name-spacing and conventions to, I am open to your advice.
Comment #17
mile23#1862600: Entity type names/IDs are not properly namespaced by owner (e.g., taxonomy.term vs. taxonomy_term) confirms for me why the idea of distributed all-at-once development of complex systems should induce panic attacks. :-)
Anyway, yah, now that I understand the problem, please go with 'content_entity_example_[type]' for the time being.
Comment #18
cgalli commentedCorrection user_id and language field
Comment #20
cgalli commentedSecond try, (without .gitignore being included by accident)
Next step: add tests. I waste too much time making sure everything works fine ;-)
Comment #21
cgalli commentedComment #22
cgalli commentedOk. Started with my first ever test, but somehow I am doing something wrong. The listing link does not seem to appear, so the test fails.
Any ideas?
Comment #24
mile23This doesn't actually implement getInfo(). :-) Use {@inheritdoc} instead.
You have to do a drupalGet() before there's content to test.
Comment #25
socketwench commentedAdded some stuff based on comments and work on the config entity example. Fixed list builder (nee controller) due to https://drupal.org/node/2200867.
Comment #27
cgalli commentedApplied the patch. Now I am getting the error:
Drupal\Core\Entity\EntityStorageException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'menu_name' cannot be null: INSERT INTO {menu_links} (menu_name) VALUES (:db_insert_placeholder_0); Array ( [:db_insert_placeholder_0] => ) in Drupal\menu_link\MenuLinkStorageController->save() (line 107 of /var/www/d8/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php).
I belive it has nothing to do with your changes....
Comment #28
cgalli commentedTypo, I believe. When changed to 'buildForm', it stops working.
Comment #29
socketwench commentedWow. Just. And I thought I manually tested it too.
Comment #31
cgalli commentedYou did test it. And it probably worked. It just never activated the customized form but used the standard one for the name field.
I am stopping work on this until the DevDays are over. Too many moving targets....
Comment #32
cgalli commented- adapted to changes after DevDays, functional again
- basic tests working, to be expanded
Comment #33
mile23Comment #34
cgalli commentedAdded autocomplete widget to field definition for user_id
moved structure to PSR-4
Comment #35
cgalli commented- prepared for entity access controller
- test coverage
Comment #36
cgalli commentedFinished access controller
Some style corrections
With this, the basic content entity example is complete
Comment #38
cgalli commentedUnrelated test failure, see #2262989: Branch fail: SimpleTestExampleMockModuleTest and DBTNGExampleTest failing
Comment #39
mile2336: content_entity_example_36.patch queued for re-testing.
Comment #40
mile23Still would be great to have some info about what a content entity is, and why you'd use it and so forth. The whole module is kind of sparse on inline comments and other didactic stuff.
Great to have the example, though.
Comment #41
cgalli commentedI am currently transforming the example to a more real world example (contacts). In addition, we will include views integration, twig and preprocess as well as a corresponding config entity.
And yes, inline comments will eventually be added as well :-)
Comment #42
mile23I'd like to keep these modules as simple as possible. Remember they're more for new people than for someone who wants to re-implement node.
Chunking out some of those other APIs into other example modules would keep things clear, I think.
Comment #43
cgalli commentedOk, we'll keep this in mind.
I think that exposing the data to views belongs here. It's normally one of the first questions that people ask about entities. Twig and the preprocess stuff can be handled by other examples.
Comment #44
berdirYeah, defining an entity involves a number of different API's, so we have to cover them to provide a real example. Views data is useful because that's going to be the common way to display lists of content entities and the views data integration will hopefully be provided by default at some point.
A preprocess and a twig template is currently also necessary, all core entities do that, #2023571: Support preprocessing in EntityViewBuilder would cover the default preprocess stuff while there's no issue seriously trying to add a default template for entities like entity.module in 7.x had.
Comment #45
mile2336: content_entity_example_36.patch queued for re-testing.
Comment #47
mile23See the issue for a more complex content entity: #2280723: Create a bundled Content Entity Example for D8
Comment #48
socketwench commentedComment #49
socketwench commentedComment #50
mile23So I applied #36 and installed it.
Everything seems to work except for deletion... It gives the white screen of death, unable to show me the confirm form.
Also, we don't need hook_schema() any more, thanks to this issue: https://drupal.org/node/2259243
And it would be great if we could stop here for this example and work on the documentation. The goal here isn't to have a complete implementation, but to give people something to read so they can understand how all the pieces interact.
Comment #51
mile23Fixed issue with getCancelRoute() for https://drupal.org/node/2189619
Comment #52
cgalli commentedBack after busy times...
I am currently working on renaming and adapting to chances in core (PSR-4, schema etc).
As soon as this is done I will adapt documentation (inline and here: https://drupal.org/node/2192175).
Ok?
Is there a timeline for the example modules to be finished (beta, RC, Final)?
Comment #53
mile23Timeline: FINISH NOW! :-)
Examples is always in a dev state; there aren't any releases. The things that matter are: 1) Whether the documentation is accurate, and 2) whether the tests pass.
Comment #54
cgalli commentedok:-) working on it.
Comment #55
cgalli commentedNow....
- Changed naming to make it more readable.
- PSR-4
- Schema removed
- Tests included
- Includes change proposed in #51
Please specify the sort of documentation you expect, thanks.
Comment #56
mile23Changed menu link name to reference the example module. Added hook_help() to give some context to the contact listing, and a link to the admin page.
Comment #58
cgalli commentedFixed tests
Comment #59
mile23Comment #60
cameron tod commentedThe last patch file is empty :)
Comment #61
mile23Woops... Seems like the testbot would fail that. Guess not.
Here's #56 with the interdiff from #58.
Comment #62
mile23Still needs a ton of documentation. Look at other examples, especially config_entity_example, to see what's needed.
Basically, Examples are a how-to tutorial that you can run.
Comment #63
mile23Comment #64
cgalli commentedwill do...
Comment #65
vacho commentedWhen I try to enable the module "content_entity_example" of the #61 patch
This message appear and drupal8 fail
Error
Status message The configuration options have been saved.
The website has encountered an error. Please try again later.
Comment #68
mile23Ah, more branch blockers. Yay.
Comment #69
cgalli commentedWill resume work coming tuesday :-)
Comment #72
cgalli commentedWorking again against latest D8.dev.
Tests passing locally.
Removed issue tags
Comment #73
mile23Comment #75
cgalli commentedAll tests are example modules fatal errors.
I am not sure if my code triggers these fails.
Any idea what this could be?
Comment #76
mile23Looks like another branch blocker.
Like this: https://twitter.com/socketwench/status/485812535455526913
Comment #77
berdirrandomName() got renamed to randomMachineName()...
Comment #79
mile23Now that the branch blocker is out of the way... :-)
This is great and I appreciate the effort!
A few things:
Ewps.
I'm sure there's more to say about how an access controller works.
Formatting error, and also tell me why you create an interface and what it gets used for.
Formatting.
Walk us through the annotations and why you set them the way you did.
Wouldn't that be 'Contact'?
We really need some explanation of how this fielding system works, and why we need it even though we have all the annotations.
"..abstract submitForm() method."
Also @group content_entity_example and @group examples
Comment #80
berdir5. It is not possible to add inline comments on annotations. What I'd suggest is a short summary of the interesting parts and then add a reference to \Drupal\Core\Entity\EntityType, where the properties are documented. One important part there is the admin-form thing.
Comment #81
mile23That's basically what I meant: A piece in the docblock explaining some of the options and the decision process.
Comment #82
cgalli commentedChecked for style
Added documentation inline
Please check for correctness
Let me know if things are missing
Comment #84
cgalli commentedFixed tests
Comment #86
mile23I just fixed the same problem in the branch last night: https://www.drupal.org/node/2200867 "Entity "controllers" are renamed"
Comment #87
mile23Getting close... :-)
This API changed: https://www.drupal.org/node/2200867
Thanks for the huge improvement in the docs.
Just to let you know, though: We can do nested lists in doxy. Otherwise this will get parsed into a bunch of paragraphs. https://www.drupal.org/coding-standards/docs#lists
Comment #88
cgalli commentedHopefully even closer :-)
Simplified help text structure, let's what doxy makes of it.
Adapted to the AcessControlHandler API changes.
Tests pass locally against the latest D8 pull....
Comment #89
mile23Moved hook_help() content to the list builder.
Added some tests for the paths.
I'm not really sure how we're supposed to be using @package, so I left that in.
Fixed a few formatting errors.
Comment #90
mile23And with that... We're done!
Thanks, everyone, but especially cgalli for sticking with it. :-)
Comment #92
cgalli commentedYay :-)
Comment #94
kpv commentedIt seems that Views integration should be added here since all core content entities do.
Comment #95
berdirviews integration was postponed on the EntityViewsData handler to land, which is being worked on now: #1740492: Implement a default entity views data handler
And we should do that in a new issue I think.
Comment #96
kpv commentedThere was a change in entity annotation: Entity controller admin-form annotation replaced by field_ui_base_route
Should we post required changes into the current issue or open new issues when core api changes happen (like this one)?
Comment #97
mile23New issues, please.
Thanks.