Updated in comment #25

Problem/Motivation

As we are moving the code base to OOP, we want to replace entity_create() by its OOP equivalent.

This discussion started in #2345607: Translated taxonomy terms not rendered in the entity display language where it was decided that entity_create should only be used when the entity type is unknown or stored in a variable. If the node type is known, and passed as a string, the create method should be called on the specific entity type class.

In #9, @jhedstrom suggested that this function should be replaced by a static method of EntityManager.
Between #13 and #22 it has been decided that, regarding the number of case where the entity type is variable, we should use the full call to \Drupal::entityManager()->getStorage($entity_type)->create($values) directly.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Task
Issue priority Not critical because it's only about good practices
Prioritized changes The main goal of this issue is DX and performance. (DX because it increases code consistency and performances because it avoids call to EntityManager when they are not absolutely needed)
Disruption Not disruptive because the old function is only marked as deprecated and not removed.

Proposed resolution

Add a clear comment on entity_create() to mark it as deprecated and explain the two cases clearly.

Remaining tasks

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions Done
Update the issue summary Instructions Done
Update the issue summary noting if allowed during the beta Instructions Done
Manually test the patch Novice Instructions
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions

User interface changes

None.

API changes

entity_create() is now @deprecated

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir’s picture

The question is if we should actually keep entity_create() as a function, as we are removing most wrapper functions like this.

The OOP/D8 way is \Drupal::entityManager()->getStorage($entity_type)->create(). Which is a bit long...

kmoll’s picture

I created a patch that would deprecate it and add what should be done instead. As far as the debate, I am usually a fan of wrapper functions, but a bigger fan of consistency. If wrappers are being removed in core maybe it would be better to remove it and go with the entityManager.

The question I have is, should this be used only when $entity_type is a variable, as apposed to a known String, as in the case of creating a node? IE. $node = Node:create($values).

kmoll’s picture

Status: Active » Needs review
jhodgdon’s picture

Component: documentation » entity system

Sounds like this needs to be in the entity system component for a decision on whether to document and keep, deprecate, or remove this function. And the patch doesn't accomplish what is in the issue summary either...

kmoll’s picture

There was another issue created for it, https://www.drupal.org/node/2346253, so the patch above was only meant to handle the deprecation, if in fact that is what is decided upon.

kmoll’s picture

or maybe we should mark this as a duplicate and merge this into the patch there?

jhodgdon’s picture

Hm... That other issue at least the title is only about Taxonomy. So ... not sure. But the issue summary here is talking about documenting that this function shouldn't be used unless the entity type is unknown or in a variable, and this patch doesn't do that. Marking it deprecated is not the same thing. So we need (a) a decision and (b) probably a new patch.

kmoll’s picture

ok, I agree, if we can get a decision, I can update the patch.

jhedstrom’s picture

Status: Needs review » Needs work

I agree that we can't just mark it deprecated without a better replacement than the current OOP way. Many, many contrib modules use entity_create(), and I'd prefer at least a helper method on the entity manager so it could be called as EntityManager::create() or some such.

DuaelFr’s picture

Title: Update entity_create() documentation » Deprecate entity_create() in favor of a new EntityManager::create() method.
Priority: Minor » Normal
Issue summary: View changes
Status: Needs work » Needs review
FileSize
1.65 KB

I came to that issue looking around for entity_create replacement rules.
I don't know where to put that patch that introduces the EntityManager::create() static method.

I didn't include the #2 patch as it seems to be applied on the wrong method.

DuaelFr’s picture

Issue summary: View changes
Dave Reid’s picture

So.... how would this work if something like file_entity wants to swap out the entity class being used for a specific entity type?

Berdir’s picture

Status: Needs review » Needs work

That works just fine, the new method is identical to the existing one, and create() works too, it works both for the original class and the one that was replaced, I made sure of that and I'm actively using that in our file_entity port.

However, not convinced about adding a method like that here. First, it should definitely not be static. Second, we already have multiple issues about introducing factory methods and/or making the existing ones work. See #1867228: Make EntityTypeManager provide an entity factory and #2015535: Improve instantiation of entity classes and entity controllers. They would however have slightly different purpose and that's exactly the problem (creating an object vs. creating a new entity and applying default values). Naming is hard there..

Dave Reid’s picture

@Berdir: Yeah, seeing get_called_class() in Entity::create() seemed very suspect for me, given that we'd be hard-coding calling Drupal\file\Entity\File::create() and not Drupal\file_entity\Entity\File::create() throughout core and other contrib modules.

DuaelFr’s picture

What would you think about moving this method to \Drupal\Core\Entity\Entity and call it something like createFromType() ? Would it be better ?
I think having a static helper for this kind of use is far better from a DX point of view than having to remember \Drupal::entityManager()->getStorage($entity_type)->create($values);. Although, there are only 81 occurences of this case (entity_create on a variable entity type) in Core, I think that contrib would use it a lot.

tim.plunkett’s picture

+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -1438,4 +1438,22 @@ protected function deleteLastInstalledFieldStorageDefinition(FieldStorageDefinit
+    return \Drupal::entityManager()

Referring to the service within itself is strange. I would just stick to using the longhand.

Berdir’s picture

Every example of entity_create($entity_type... that I can see in core is in tests And almost all of them are in field/entity tests. Contrib will not write tests like that. I have 55 modules in my modules folder, and exactly one call like that.

load(), loadMultiple() are actually more likely to be used in a generic way, we'd have to add corresponding methods like that as well. But again, almost all remaining calls there are in tests, everything else already has been converted to use getStorage(), often from an injected entity manager or entity storage.

This is IMHO not worth polluting the already way too big entity manager interface.

DuaelFr’s picture

So, what's your decision?
Do you want me to create an helper or du you want me to replace these 81 occurences by the long syntax and indicate this way to solve the deprecation?

webchick’s picture

It would be nice to get an answer to #18 so we could continue with #2490966: [Meta] Replace deprecated usage of entity_create with a direct call to the entity type class in some fashion. It would be a shame to ship D8 with entity_create() everywhere, given the importance of the entity API to D8 and the amount of work given to modernize other parts of the API.

DuaelFr’s picture

I guess the answer is that we should use

$this->entityManager->getStorage($entity_type)->create($values);

or

\Drupal::entityManager()->getStorage($entity_type)->create($values);

according to the availability of the manager in the scope.

I don't really know how to write that in a comment. Do you think the following is going to be unerstandable?

  * @deprecated in Drupal 8.x-dev, will be removed before Drupal 9.0.0. Use
 *    the <EntityType>::create() method if the entity type is known or
 *    <EntityManager>->getStorage($entity_type)->create($values) if the entity 
 *    type is variable.
alexpott’s picture

+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -1438,4 +1438,22 @@ protected function deleteLastInstalledFieldStorageDefinition(FieldStorageDefinit
+  public static function create($entity_type, array $values = array()) {
+    return \Drupal::entityManager()
+      ->getStorage($entity_type)
+      ->create($values);
+  }

I don't think we should add this static method. We should just tell people to do \Drupal::entityManager()->getStorage($entity_type)->create($values); if the entity type is a variable. I agree with @Berdir in #17 and others.

Re #20 I would do something like:

 * @deprecated in Drupal 8.x-dev, will be removed before Drupal 9.0.0. Use
 *    the <EntityType>::create() method if the entity type is known or
 *    \Drupal::entityManager()->getStorage($entity_type)->create($values) if the entity 
 *    type is variable.
DuaelFr’s picture

Status: Needs work » Needs review
FileSize
1.79 KB
695 bytes

It seems that we have an agreement.
Here is the patch.

Crell’s picture

Status: Needs review » Reviewed & tested by the community

I prefer not adding static methods, too. :-)

Berdir’s picture

Status: Reviewed & tested by the community » Needs work

Yes, but the issue title and summary still talks about doing that.

DuaelFr’s picture

Title: Deprecate entity_create() in favor of a new EntityManager::create() method. » Deprecate entity_create() in favor of a <EntityType>::create($values) or \Drupal::entityManager()->getStorage($entity_type)->create($values)
Issue summary: View changes
Status: Needs work » Needs review

@Berdir IS and title updated. Thank you for your review.

Crell’s picture

Status: Needs review » Reviewed & tested by the community

IS is now accurate.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 6cf71a2 and pushed to 8.0.x. Thanks!

Docs only changes are not frozen in beta.

  • alexpott committed 6cf71a2 on 8.0.x
    Issue #2346261 by DuaelFr, kmoll, Berdir: Deprecate entity_create() in...
DuaelFr’s picture

Issue summary: View changes

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.