Answers.Body: <p>Yes and no. 
  Yes it is possible to include as many additional segments to <strong>selected</strong> routes and it's even possible to achieve what you want but it might become resource heavy and you would need to handle the entire routing on your own.</p>
  
  <h3>Channels</h3>
  
  <p>If it's for a channel with a set <code>URI</code> format like <code>foo/{slug}</code> you can implement a route like</p>
  
  <pre class="lang-php prettyprint-override"><code>Event::on(
      UrlManager::class,
      UrlManager::EVENT_REGISTER_SITE_URL_RULES,
      function(RegisterUrlRulesEvent $event) {
          $event-&gt;rules[] = [
              'pattern'  =&gt; 'foo/&lt;uri:\S+&gt;/&lt;additionals:\S+&gt;',
              'route'    =&gt; 'your-module/your-controller/route',
              'defaults' =&gt; [
                  'additionals' =&gt; ''
              ]
          ];
      }
  }
  </code></pre>
  
  <p>So all your urls like <code>foo/{slug}</code> as well as <code>foo/{slug}/bar/whatever</code>  will be routed to your controller <code>YourController::actionRoute</code> with the parameters </p>
  
  <pre class="lang-php prettyprint-override"><code>public function actionRoute(string $uri, string $additionals = null)
  {
      $element = Craft::$app-&gt;getElements()-&gt;getElementByUri($uri);
      $template = (new Query())-&gt;select('template')
          -&gt;from('sections_sites')
          -&gt;where(['=', 'siteId', $element-&gt;site-&gt;id])
          -&gt;andWhere(['=', 'sectionId', $element-&gt;sectionId])
          -&gt;scalar();
  
      return $this-&gt;renderTemplate($template, ['entry' =&gt; $element]);
  }
  </code></pre>
  
  <p><strong>Note</strong> keep in mind this will only work if the <code>uri</code> format is rather simple like <code>foo/{slug}</code> it won't really work for things like <code>foo/{author}/{category.id}/{slug}/{title}</code> you'll need the rule mentioned in "structures" for it</p>
  
  <h3>Singles</h3>
  
  <p>If it's for singles you can do it dynamically </p>
  
  <pre class="lang-php prettyprint-override"><code>try {
      $uris = (new Query())
          -&gt;select('uriFormat')
          -&gt;from('sections_sites')-
          -&gt;where(['=', 'siteId', Craft::$app-&gt;getSites()-&gt;getCurrentSite()-&gt;id])
          -&gt;andWhere(['=', 'sectionId', [array of your section ids])
          -&gt;column();
  } catch (Exception $exception) {
      $uris = [];
  }
  
  if (empty($uris) === false) {
      $event-&gt;rules[] = [
          'pattern'  =&gt; '&lt;uri:(' . implode('|', $uris) . ')&gt;' . '/&lt;additional:\S+&gt;',
          'route'    =&gt; 'module/controller/action',
          'defaults' =&gt; [
              'additional' =&gt; ''
          ]
      ];
  } 
  </code></pre>
  
  <h3>Structures</h3>
  
  <p>For structures it's not that easy... You would need to recursively remove one segment and try to search for a matching route if there is one, use it, otherwise remove the next one.</p>
  
  <p><strong>Attention pseudocode</strong></p>
  
  <pre class="lang-PHP prettyprint-override"><code>$path = get your full path
  while($element === null){
      $path = $path - lastSegment;
      $element = Craft::$app-&gt;getElements()-&gt;getElementByUri($path);
  }  
  // attach the route `path` as you can see above
  </code></pre>
  
  <p>However I would <strong>not</strong> suggest the code above since it will search for a matching element for each segment for <strong>every</strong> request. I would highly recommend to include many conditions around it like <code>Craft::$app-&gt;getRequest()-&gt;isSiteRequest() === true</code> and <code>$request-&gt;isAjaxRequest() === false</code> and so on to reduce the amount of queries as much as possible</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-11-01T18:51:04.040Z
Answers.LastActivityDate: 2018-11-01T19:05:31.493Z
Answers.LastEditDate: 2018-11-01T19:05:31.493Z
Answers.UserDisplayName: Robin Schambach
Body: <p>In EE, if there was a template <code>/foo/bar.html</code>, one could access the contents of that template by going to either <code>example.com/foo/bar</code> or <code>example.com/foo/bar/more/segments/here</code>. The additional URL segments didn't prevent EE from loading the most-accurately-matching template.</p>
  
  <p>Moving over to Craft, <code>bar</code> is now an entry's slug. The section for that entry is properly set up with the "Entry URI Format" and "Template" pointing to <code>foo/{slug}</code> and <code>foo/_entry.html</code>, respectively. Is there a way to get the same "most-accurate" template-matching behavior in Craft? Perhaps with routes? I would want the <code>{{ entry }}</code> variable to be automatically available for either URL.</p>
  
Tags: <templating><routes><segments>
Title: Templates, Routes, and URL segments
ThreadText: # Templates, Routes, and URL segments
  
  (Asked by: username_0 on 2018-11-01)
  
  In EE, if there was a template `/foo/bar.html`, one could access the contents of that template by going to either `example.com/foo/bar` or `example.com/foo/bar/more/segments/here`. The additional URL segments didn't prevent EE from loading the most-accurately-matching template.
  
  Moving over to Craft, `bar` is now an entry's slug. The section for that entry is properly set up with the "Entry URI Format" and "Template" pointing to `foo/{slug}` and `foo/_entry.html`, respectively. Is there a way to get the same "most-accurate" template-matching behavior in Craft? Perhaps with routes? I would want the `{{ entry }}` variable to be automatically available for either URL.
  
  **Tags:** templating, routes, segments
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-11-01. Score: 2 | Accepted answer
  
  Yes and no.
  Yes it is possible to include as many additional segments to **selected** routes and it's even possible to achieve what you want but it might become resource heavy and you would need to handle the entire routing on your own.
  
  ### Channels
  
  If it's for a channel with a set `URI` format like `foo/{slug}` you can implement a route like
  
  ```php
  Event::on(
      UrlManager::class,
      UrlManager::EVENT_REGISTER_SITE_URL_RULES,
      function(RegisterUrlRulesEvent $event) {
          $event->rules[] = [
              'pattern'  => 'foo/<uri:\S+>/<additionals:\S+>',
              'route'    => 'your-module/your-controller/route',
              'defaults' => [
                  'additionals' => ''
              ]
          ];
      }
  }
  
  ```
  
  So all your urls like `foo/{slug}` as well as `foo/{slug}/bar/whatever` will be routed to your controller `YourController::actionRoute` with the parameters
  
  ```php
  public function actionRoute(string $uri, string $additionals = null)
  {
      $element = Craft::$app->getElements()->getElementByUri($uri);
      $template = (new Query())->select('template')
          ->from('sections_sites')
          ->where(['=', 'siteId', $element->site->id])
          ->andWhere(['=', 'sectionId', $element->sectionId])
          ->scalar();
  
      return $this->renderTemplate($template, ['entry' => $element]);
  }
  
  ```
  
  **Note** keep in mind this will only work if the `uri` format is rather simple like `foo/{slug}` it won't really work for things like `foo/{author}/{category.id}/{slug}/{title}` you'll need the rule mentioned in "structures" for it
  
  ### Singles
  
  If it's for singles you can do it dynamically
  
  ```php
  try {
      $uris = (new Query())
          ->select('uriFormat')
          ->from('sections_sites')-
          ->where(['=', 'siteId', Craft::$app->getSites()->getCurrentSite()->id])
          ->andWhere(['=', 'sectionId', [array of your section ids])
          ->column();
  } catch (Exception $exception) {
      $uris = [];
  }
  
  if (empty($uris) === false) {
      $event->rules[] = [
          'pattern'  => '<uri:(' . implode('|', $uris) . ')>' . '/<additional:\S+>',
          'route'    => 'module/controller/action',
          'defaults' => [
              'additional' => ''
          ]
      ];
  } 
  
  ```
  
  ### Structures
  
  For structures it's not that easy... You would need to recursively remove one segment and try to search for a matching route if there is one, use it, otherwise remove the next one.
  
  **Attention pseudocode**
  
  ```PHP
  $path = get your full path
  while($element === null){
      $path = $path - lastSegment;
      $element = Craft::$app->getElements()->getElementByUri($path);
  }  
  // attach the route `path` as you can see above
  
  ```
  
  However I would **not** suggest the code above since it will search for a matching element for each segment for **every** request. I would highly recommend to include many conditions around it like `Craft::$app->getRequest()->isSiteRequest() === true` and `$request->isAjaxRequest() === false` and so on to reduce the amount of queries as much as possible
  
  
  ---
  
  