How to perform routing in CakePHP 1.2
CakePHP introduces a new way of writing your routes, you can now restrict your URLs at parameter level, meaning that we can now specify URLS like /date/:year/:month instead of /date/*. This post compares CakePHP 1.1 and 1.2 routing differences. I’ll start with showing the old way first:
CakePHP 1.1 way
In CakePHP 1.1, routings looks like this in /app/config/routes.php:
And the corresponding method in the controller would look something like this:
$posts = $this->Post->findAll(
"MONTH(pub_date)=$month AND YEAR(pub_date)=$year"
);
$this->set(‘posts’, $posts);
}
CakePHP 1.2 way
There isn’t much changes in CakePHP 1.2’s routing handling statement except that now it uses 2 colons.
No change in the controller’s method.
$posts = $this->Post->findAll(
"MONTH(pub_date)=$month AND YEAR(pub_date)=$year"
);
$this->set(‘posts’, $posts);
}
But what if there’s a need for constricting the user to only certain years and months at URL level. I don’t know about you, but I don’t have posts in year 1954. I don’t want people passing invalid arguments into URLs too. You can pass the following URLs:
- /date/2008/3/
- /date/whatever/122211/
- /date/1954/20/
The above examples are all valid routes but the database don’t have a valid match. So we can try do stricter routings in CakePHP 1.2.
CakePHP 1.2 ’stricter’ way
In /app/config/routes.php of CakePHP 1.2:
The year field would match any year from 2000 to 2999 inclusive. The month field would match any months 1 to 9 or 10, 11 and 12. That should cover all the months. This is how your method would look like:
$year = $this->params[‘year’];
$month = $this->params[‘month’];
$posts = $this->Post->findAll(
"MONTH(pub_date)=$month AND YEAR(pub_date)=$year"
);
$this->set(‘posts’, $posts);
}
Note that now p_date() method doesn’t take any arguments, instead you retrieve the URL using $this->params['year']. If users try to access an invalid URL, the user will get some 404 page. And since the URL is invalid, the method will not be invoked, this saves the database from being called unnecessarily.
I like it that the preg_match is now done at the Router instead of in the method itself. It makes things a lot neater in the long run.
Possibly related:
If you use the CakePHP version from the development branch you can simplify your example even more:
Router::connect(‘/date/:year/:month’, array(‘controller’ => ‘posts’, ‘action’ => ‘p_date’), array(‘year’ => $Year, ‘month’ => $Month));
Apr 26
@Daniel Hofstetter: Nice tip! I have the development version actually and I haven’t realized that.
Apr 27
hi
I want to do this
http://localhost/cake/Users/1/
trying with
Router::connect(
“/:controller/:id”,
array(“action” => “view”, “[method]” => “GET”, ‘id’=>’:id’),
array(‘id’ => ‘[0-9]+’)
);
but it does not pick id in view($id).
any help plz?
May 15
Hi atta, I think what you wanted to do instead would be
"/:controller/:id",
array("action" => "view", "[method]" => "GET"),
array("id" => "[0-9]+")
);
By specifying “id” => “:id”, it results in an infinite loop.
May 15