<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>

CC BY-SA 4.0
2018-11-01T18:51:04.040Z
2018-11-01T19:05:31.493Z
2018-11-01T19:05:31.493Z
Robin Schambach
<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>

<templating><routes><segments>
Templates, Routes, and URL segments
# 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
Event::on(
    UrlManager::class,
    UrlManager::EVENT_REGISTER_SITE_URL_RULES,
    function(RegisterUrlRulesEvent $event) {
        $event->rules[] = [
            'pattern'  => 'foo//',
            '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 
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 
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'  => '' . '/',
        '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
$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


---

