2
votes

Is it possible to have pages route without the controller in the URL but still have other controllers work? Example:

Doing the following works for having the pages without /pages/ in the URL but if I try to access any other controller it doesn't work:

  • From: Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  • To: Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'index'));

Is there a way to setup the Router so that it runs controller/action if it exists. If it does not it runs the pages controller/action?

3
I'm wrapping my head around your question and still cant quite get it. You would like to match 2 different controllers /w actions with one URL? Btw you should know what actions are available to you and create routes accordingly. From the last line of your question I imagine that you have URL which contains controller and action, right? And if it does not exists you want to run some action from pages controller? Well you see, I really cant make any sense from this so if you explain it somehow to me I might be able to help you. - user2074884
@luboss Thanks for your involvement and I apologize for my lack of clarity. Basically I want pages to be accessible at domain.com/pagename but creating a route for that means that if I try to access a controller it won't work because it thinks the controller is a page. Example: For domain.com/users/edit/1 Cake would think users is a page rather than a controller.... For now I went with Dave's answer. I don't think there's really a "solution". The only way is to explicitly tell Cake which routes are pages. - iDev247
Ok I get it now. I think the ability to match parameters via regular expressions is the best you can get so yes you did right. However if you define route like this Router::connect('/:pagename', array('controller' => 'Pages', 'action' => 'display')); and in display action you grab the parameter like this $pagename = $this->params->pagename; the other url (domain.com/users/edit/1) would remain unaffected because it has extra bits that arent covered in just defined route (/edit/1) this way you dont have to enumerate page names as long as you dont have conflicting url matches. - user2074884
Of course it would affect URL when trying to access index function of some controller like domain.com/users instead of domain.com/users/index but you can solve this by putting something unique in your defined pages route or differentiate it by giving that url an .html extension. - user2074884

3 Answers

3
votes

I think the short answer is, no - it's not possible in the manner you're hoping*. Routing isn't really "logic" driven, so unless you can come up with a way to match the things you want in both respects you can't do "if controller exists, then _, else _" kind of thing.

*You could, however add each "page" as a row in your routes file. That would allow "about", "contact" ...etc to be accessed directly, while things that don't exactly match them are handled by the remaining routes.

3
votes

I know I'm late, but here's my tip for someone looking for this.

In routes.php

foreach(scandir('../View/Pages') as $path){
  if(pathinfo($path, PATHINFO_EXTENSION) == "ctp"){
    $name = pathinfo($path, PATHINFO_FILENAME);
    Router::connect('/'.$name, array('controller' => 'pages', 'action' => 'display', $name));
  }
}

This will create a route for every ctp file in the View/Pages folder.

0
votes

I actually solved this the opposite way from Dave's answer above, by adding a route for each controller, rather than each page. (I won't be adding new controllers very often, but I will be adding new content on a regular basis.)

// define an array of all controllers that I want to be able to view the index page of
$indexControllers = array('posts','events','users');

//create a route for each controller's index view
foreach ($indexControllers as $controller) {
    Router::connect(
        '/' . $controller,
        array(
            'controller' => $controller,
            'action' => 'index'
        )
    );
}

//create a route to remove 'view' from all page URLs
Router::connect(
    '/:title',
    array(
        'controller' => 'contents',
        'action' => 'view'
    ),
    array(
        'pass' => array('title'),
        'title' => '[a-z0-9_\-]*'
    )
);