How do I make my urls reflect the page hierarchy I have defined in the CMS? eg. example.com/labs/project-one rather than simply example.com/project-one
SilverStripe doesn't actually do that...I've managed to write a hack for it, but you'd have to be fairly keen - it's ugly and not tested in production yet.
Might be easiest to just live with the one-level URLs for now.
Ok, thanks Nathan. I'd like to put in a vote for that feature/option to get tested and produced :)
I second that feature. Especially for larger sites that tend to have a lot of articles it can be very beneficial to have the URL's structured this way to stop an overlap in article names.
The problem is that example.com/labs/project-one is interpreted as being the project-one action on the labs pags.
It's possible that for specific URLs we could allow the ability to set pages up - by disallowing any actions to be called on the labs page in the preceeding example.
Nathan - how do you deal with this issue in your patch?
My solution's a bit messy - I put all my custom code into a seperate NathanHacks class to make upgrading easier, so it might be a little different if you wanted to integrate it.
Very basically what is does is make a NathanHacks singleton that loads a copy the site tree, then loops through (using parent()) and creates a nested array of pages, like the site tree.
Then it hijacks Director::getControllerForURL() if you get a ModelAsController (or a RootURLController, it also gets rid of the /home redirect) and loops through the top level of the nested array, looking for a page with $urlParts. If it finds it, it then searches that page's children for $urlParts and so on until there are no more urlParts.
For example, it gets the url "/flying/monkey". It'll loop through all the top level pages looking for a URLSegment of "flying". If it finds one, it sets that page to $currentPage, then loops through $currentPage's children looking for a URLSegment of "monkey". If there is no "monkey", it instead checks to see if "monkey" is a method of $currentPage. If it's not that either, it 404s.
The point of the singleton is to store extra data like each page's full url ("/flying/monkey" as well as just "/monkey") and other bits and pieces for later use. Like returning the full URL in SiteTree's Link() and whatnot. There are about 11 points in SIlverStripe that call NathanHacks at the moment, I think.
Does that make sense?
Thanks for the explanation - it seems like this would be quite slow on a large site tho - how did you find this went?
It works fine for me but so far I've only used it on a little site, so you could be right. My plan is to refactor some time and keep growing the test site to see what happens.
Do you think it would help NathanHacks stored the pages in a flat array by URL? So going to /flying/monkey would just look for $page['flying/monkey'] rather than running through the loop...of course, you'd still need to do the whole big loop the first time to make that array.