Score:2

Can routing use parameters already in the URL?

cn flag

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 ?

Jaypan avatar
de flag
You didn't show the code you are using to generate the URL that is causing the error.
Jaypan avatar
de flag
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.
cn flag
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 ?
Score:2
cn flag

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;
  }
cn flag
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.
4uk4 avatar
cn flag
IMHO this protected method exists only to be overridden in such use cases.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.