Routing: How to create a route with unlimited url segments?

<%- if @topic_view.topic.tags.present? %>
<%= t 'js.tagging.tags' %>: <%- @topic_view.topic.tags.each do |t| %> <%= t %> <%- end %>
<% end %>

Silverstripe Version: 4.5.1

Question:

Hi, I’m really not sure if this kind of problem has already been covered here, as it seems that routing problems presented on this forum vary a lot and are generally quite complex - at least to me :D.

This is what I’m trying to achieve:
A route that recognises a url like this: http://mysite.com/go/123/an/undefined/amount/of/url/segments . The route should always call one single method in a controller class.

I’ve already achieved a solution that recognises a url like this: http://mysite.com/go/123 . But if the url contains more sub segments, I will get a 404 Page not found error.

app/_code/routes.yml:

---
Name: approutes
After:
  - '#rootroutes'
  - '#coreroutes'
---
SilverStripe\Control\Director:
  rules:
    'go//': MyController

MyController.php:

class MyController extends Controller
{
	private static $allowed_actions = [
		'go' ,
	];
	
	private static $url_handlers = [
		'$ObjectID!/$OtherOptionalStuff' => 'go',
	];
	
	public function go()
	{
		// ...
	}
}

Thank you for your support! :slight_smile: I appreciate it! :slight_smile:

There must be a better way I guess, but can you just do '$ObjectID!/$1/$2/$3/$4/$5/$6/$7/$8' => 'go' for as many params as you may need? $1 - $8 would be optional so that should let you have between 0 and 8 extra segments and still call the go method. That would only work of course if you have a concrete upper limit.

Thanks, I think this is the tradeoff that I will need to make, at least to make it work in the first place. I just need to define parameters up to something like $99 so that the upper limit is high enough. Not clean, but at least will work :). And if someone else comes up with a more elegant solution, I can then switch to that :).

Generally, I would try to get away from this design pattern /for/bar/234/54/234/234234/hello

as it is not very readable and can easily lead to errors.

maybe try:

http://www.awesome.com/go/?name=foo&test=bar&code=234, etc… this means you can have loads of arguments and they are specifically assigned rather than relying on order for meaning.

Of course I do not know your specific situation.

Just a heads up SS 4.6 will be getting Wildcard URL params which I think is what you’re after… it was only merged in yesterday - NEW: Variadic URL parameter matches for url_handlers (#9438) · silverstripe/silverstripe-framework@1fb574a · GitHub

2 Likes

Thank you for your suggestion. I think this would be a good solution in many cases. However, I need to support slashes in this particular case. To explain why, I will need to refine my above example uri in more detail:

http://mysite.com/go/123/www.example.com/an/undefined/amount/of/url/segments

I added www.example.com/ to the url. So the uri starts with the go part, after which there will be an ID number, and after that there will be a human readable url address to another website, where the controller will redirect the client’s web browser to after handling an action. To be honest, the www.example.com part and anything after it could be omitted from the url, because the ID number tells the controller where the user should be redirected to. I just want to include the www.example.com part in the url to give a hint to the user where they will end up if they click a link that has the url http://mysite.com/go/123/www.example.com/an/undefined/amount/of/url/segments.

If I would want to, I could convert the www.example.com url part to one query parameter, but I wouldn’t like it because the slashes of the url would not be so readable anymore: http://mysite.com/go/123?url=www.example.com%2Fan%2Fundefined%2Famount%2Fof%2Furl%2Fsegments