2

I'm actually using D9 to build a system with entities using sub-entities. The main entity system use the following path : /item/{item} Each sub entity is related to a main entity and use this path : /item/{item}/sub_item/{sub_item}

So to access the edit or delete form, the following pathes are required :

/item/{item}/sub_item/{sub_item}/edit /item/{item}/sub_item/{sub_item}/delete

For example : /item/1/sub_item/4/edit

I declared the following route :

entity.sub_item.edit_form:
  path: '/item/{item}/sub_item/{sub_item}/edit'
  defaults:
    _entity_form: 'sub_item.edit'
    _title: 'Edit sub item'
  options:
    _admin_route: TRUE
    parameters:
      item:
        type: entity:item
        with_config_overrides: TRUE
      sub_item:
        type: entity:sub_item
        with_config_overrides: TRUE
  requirements:
    _permission: 'administer site configuration'

Edit and Delete links are generated by list builder from getOperations. The list builder is on the following route : /item/1/sub_items (this is the "collection" to show the sub-items attached to main item).

I was hoping that the fact the current URL contained item/{item} can be directly re-used by the link generator, but it's not the fact...

Symfony\Component\Routing\Exception\MissingMandatoryParametersException : Some mandatory parameters are missing ("item") to generate a URL for route "entity.sub_item.edit_form". in Drupal\Core\Routing\UrlGenerator->doGenerate() (line 181 of /core/lib/Drupal/Core/Routing/UrlGenerator.php).

I tried to build a specific htmlRouteProvider class for my sub-item entity class but in this case too, the routes are built when cache are cleared, and I don't have access to the item in the URL to set it...

So... My question is : I'm missing something to do it easily, or must I re-implement the "toUrl()" method of my sub-item entity class to include the new "item" parameter "on the fly" ?

Thanks in advance for any suggestion.

PS : it's the solution I have actually in my sub-item entity class :

  public function toUrl($rel = 'canonical', array $options = []) {
    $uri = parent::toUrl($rel, $options);
    $uri->setRouteParameter('item', \Drupal::routeMatch()->getRawParameter('item'));
    return $uri;
  }

But maybe a better solution can be found ?

3
  • You didn't show the code you are using to generate the URL that is causing the error.
    – Jaypan
    Feb 13 at 17:10
  • 1
    I should add, I'd probably not mess with the path to the sub element, and rather create an alias to it for the path you want.
    – Jaypan
    Feb 13 at 18:46
  • No code, this is EntityListBuilder::getDefaultOperations who build automatically the links showed in the "operations" column of the list. So I can override it, or override sub-method like Entity::toUrl or Entity::urlRouteParameters like suggested by @4k4. I asked myself if there is another "magic way", like declaring specific element into the routing.yml file, ie : options: parameters: item: type: entity:{item} # <- using brackets for example ?
    – titouille
    Feb 14 at 12:58

1 Answer 1

2

I would override SubItem::urlRouteParameters() and make this independent from the current route match so that the entity can build links on all pages:

  protected function urlRouteParameters($rel) {
    $parameters = parent::urlRouteParameters($rel);
    // assuming the parent relationship is a reference field
    $parameters['item'] = $this->parent->target_id;
    // if the reference field is in the parent you have to run an entity query
    return $parameters;
  }
2
  • Ok. entity->toUrl() call entity->urlRouteParameters() to retrieve parameters of route. It's just a level higher. But if there is no other way I'm ok to override one of these two method. Thanks for your suggestion.
    – titouille
    Feb 14 at 13:02
  • 1
    IMHO this protected method exists only to be overridden in such use cases.
    – 4uk4
    Feb 14 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.