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_\-]*'
    )
);