Providing default route value for entity forms is not possible

Created on 5 November 2017, about 7 years ago
Updated 2 April 2024, 9 months ago

If you try to create a static route for adding an entity you cannot provide the entity type as a default.

e.g.:
The following route is not working. You get an:

Drupal\Core\Entity\EntityStorageException: Missing bundle for entity type example in Drupal\Core\Entity\ContentEntityStorageBase->doCreate() (line 83 of core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php).
entity.example.add_onboarding_form:
  path: '/example/onboarding'
  defaults:
    _entity_form: example.onboarding_add
    _title: 'Create an onboarding example Entity'
    example_type: 'my_bundle'
  requirements:
    _permission: 'edit example entities'
  options:
    parameters:
      example_type:
        type: entity:example_type

But this is working
e.g.:

entity.example.add_onboarding_form:
  path: '/example/onboarding/{example_type}'
  defaults:
    _entity_form: example.onboarding_add
    _title: 'Create an onboarding example Entity'
    example_type: 'my_bundle'
  requirements:
    _permission: 'edit example entities'
  options:
    parameters:
      example_type:
        type: entity:example_type

Reason is in \Drupal\Core\Entity\EntityForm::getEntityFromRouteMatch

There is this line. Where we check getRawParameter. If the placeholder is not in the route definition this is empty. The processed parameter has the correct information. And if you remove this check the right example_type gets picked up in the next line.

if (($bundle_entity_type_id = $entity_type->getBundleEntityType()) && $route_match->getRawParameter($bundle_entity_type_id)) {

What is the reason for checking the Raw Parameter here? I have no idea about the intend so its hard to say if this is a bug and if and how it can be fixed without breaking other things. Maybe somebody can enlight me.

Complete method for more context:

  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id) {
    if ($route_match->getRawParameter($entity_type_id) !== NULL) {
      $entity = $route_match->getParameter($entity_type_id);
    }
    else {
      $values = [];
      // If the entity has bundles, fetch it from the route match.
      $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
      if ($bundle_key = $entity_type->getKey('bundle')) {
        if (($bundle_entity_type_id = $entity_type->getBundleEntityType()) && $route_match->getRawParameter($bundle_entity_type_id)) {
         $match = $route_match->getParameter($bundle_entity_type_id);
          $values[$bundle_key] = $route_match->getParameter($bundle_entity_type_id)->id();
        }
        elseif ($route_match->getRawParameter($bundle_key)) {
          $values[$bundle_key] = $route_match->getParameter($bundle_key);
        }
      }

      $entity = $this->entityTypeManager->getStorage($entity_type_id)->create($values);
    }

    return $entity;
  }
🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Entity 

Last updated about 17 hours ago

Created by

🇩🇪Germany marcusx

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇬🇧United Kingdom catch

    I'm not sure I understand #26.

    The current patch looks like this:

    +++ b/core/lib/Drupal/Core/Entity/EntityForm.php
    @@ -359,10 +359,10 @@ public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entit
    -        if (($bundle_entity_type_id = $entity_type->getBundleEntityType()) && $route_match->getRawParameter($bundle_entity_type_id)) {
    +        if (($bundle_entity_type_id = $entity_type->getBundleEntityType()) && $route_match->getParameter($bundle_entity_type_id)) {
               $values[$bundle_key] = $route_match->getParameter($bundle_entity_type_id)->id();
             }
    

    Note the assignment doesn't change - that is calling ::getParameter(), it's only the if check that calls getRawParameter().

    Tagging for re-roll - this needs conversion to an MR. We can probably base the test coverage on the issues found in 📌 [PP-1] Use entity route providers for all content entity types Active or I wonder if that issue is close enough, we could rely on that issue for the test coverage and just go ahead here (once it's demonstrated that it fixes the problems over there).

  • Pipeline finished with Failed
    9 months ago
    Total: 190s
    #128955
  • 🇩🇪Germany mrshowerman Munich

    Created MR based on #21. Leaving as NW for the decision about test coverage.

  • Pipeline finished with Success
    9 months ago
    Total: 617s
    #128957
  • 🇩🇪Germany mxh Offenburg

    I'm not sure I understand #26.

    My comment #26 is too long ago to provide more context at this time. Guess I made that advise up to minimize the potential compatibility breaks, since it seems both methods are detached from each other on runtime, which is probalby not reproducable by static code checks but will pop up once recognized on runtime.

Production build 0.71.5 2024