Routing to a DataObject

Silverstripe 4.9

I’m trying to create a set of pages from DataObjects with a URL like www.mydomain.co.nz/visit/ObjectSlug:

I’m trying to do this with routing so I don’t have a Visit page in the CMS SiteTree, what is the best way to do this?
Everything I’ve tried still takes me to the home page and only works with a URL like:www.mydomain.co.nz/home/visit/ObjectSlug

---
Name: approutes
After:
  - '#rootroutes'
  - '#coreroutes'
---
SilverStripe\Control\Director:
  rules:
    'visit//$Action/$ID/$Name': 'PageController'
        public function visit(HTTPRequest $request) {
            print_r($this->getRequest()->params());

        }

PageController is really meant for pages in the CMS site tree, which you’ve said you’re trying to avoid.
I’d recommend checking this out: SilverStripe Lessons » Controller Actions / DataObjects as Pages » Silverstripe CMS I think it covers pretty much exactly what you’re trying to achieve.

Thanks for your reply Guy.
This isn’t quite what I’m after.
I’m trying to get away from is needing a page on the SiteTree called Listings.
In the example from the lesson, there’s a page called Regions where all Regions are displayed and link to the DataObject page by using the method Show. so it’s
URL/regions/show/DataObjectID, I’m wanting URL/listing/DataObjectID and Listing isn’t a page on the SiteTree.

Or is a better way of doing it, creating a page on the SiteTree, then hiding it from the client?

Right, sorry I didn’t realise how much that lesson relies on Page and PageController - but you should be able to take the overall lessons from that and use a new controller (subclass either ContentController or just directly Controller) and use routing to define the URL handler for that controller.

So in your example, you would have something like this

SilverStripe\Control\Director:
  rules:
    'visit//$Action/$ID/$Name': 'MyApp\Control\MyController'

In this case theMyController class will be given any URLs which start with /visit, which will map to its index() method, with /visit/something mapping to a something action if you defined such an action

To have example.com/listing/1 map to an object with the ID 1 you would need your rule to look like this: listing//$ID which I think would work - but you might have to experiment a bit. You would then need to dictate a url_handlers array in your controller class that has something like:

private static $url_handlers = [
  'listing//$ID' => 'index',
];

and then in the index method of the controller, you can check the ID, return a 404 if it doesn’t exist, or return the rendered template if it does.

Note also that using IDs directly on the front-end like that is a bit of an anti-pattern. You might want to look at the getUniqueKey() method on DataObject and use that instead of the database ID.

Thank you very much Guy.
I don’t think I’ve subclassed ContentController before, so that was the missing key. I was trying to use a page controller.
I’m using a unique slug as the key to each object.

Thank you for taking the time to help me with this.

1 Like