Rudiger Rudiger - 1 month ago 13
PHP Question

Custom routing without overriding core CMS routing

I'd like to implement some custom routing in my site that will end up being a database lookup to define the content returned. I've been looking at this example which isn't working as intended (mainly because it was for SS2).

I have my main routes.yml:

---
Name: mysiteroutes
After:
- 'framework/routes#coreroutes'
---
Director:
rules:
'create//$Action': 'CreateController'
'profile//$Person/$Action/': 'ProfileController'


My _config.php:

Director::addRules(2, array(
'$URLSegment//$Action/$Detail/$Option' => 'BaseController',
));


My BaseController:

class BaseController extends ModelAsController {

public function getNestedController() {
if ($this->getRequest()->params('URLSegment') =='Test') {
return new ProfileController();
} else {
return parent::getNestedController($this->getRequest()->params('URLSegment'));
}
}
}


My ProfileController:

class ProfileController extends Controller {

private static $allowed_actions = array(
'test'
);

public function index(SS_HTTPRequest $request) {
return $this->renderWith(array("ProfileHomePage", "Page"));
}

public function test(SS_HTTPRequest $request) {
print_r($request->params());
return $this->renderWith(array("ProfileHomePage", "Page"));
}
}


This works correctly without the dynamic route however I'd like to catch anything under (for example)
/example/
check if there is a db entry for it (via a custom script I'm yet to write), if not route it through the cms (i.e. check if there is a predefined route for it, then if there is a page for it before returning a 404). How can I achieve this?

I did try
'$URLSegment//$Action/$Detail/$Option': 'ProfileController'
which I could route correctly and load custom templates etc however it meant
/admin/
,
/create/
and other predefined routes wouldn't work.

Answer

Here is a way of doing it, though there might be a better way:

---
Name: mysiteroutes
---
Director:
  rules:
    'create//$Action': 'CreateController'
    'profile//$Person/$Action': 'ProfileController'
---
Name: modelascontrollerroutes
After: '#rootroutes'
---
Director:
  rules:
    '': 'HomePage_Controller'
    '$URLSegment//$ID': 'BaseController'

Base Controller:

class BaseController extends ModelAsController {

    public function getNestedController() {
        $params = $this->getRequest()->params();
        if (/*check for $params['URLSegment'] here */) {
            //return custom controller
        } else {
            return parent::getNestedController();
        }
    }
}

Example custom controller:

class PersonController extends Controller {

    private static $allowed_actions = array(
    );

    public function index(SS_HTTPRequest $request) {
        return $this->renderWith(array("PersonHomePage", "Page"));
    }
}