CakePHP RESTFul Resources, Not There Yet.
March 5th, 2009 by ScottK | 3 Comments | Filed in cakePHPNow that CakePHP 1.2 is a stable version I’ve picked back up on it. When I looked at it as a release candidate, and after they announced RESTFul routing, I specifically looked at the RESTful implementation. I’m looking at it again and find it’s still not there.
Looking at the router.php file for the Router::mapResources :
var $__resourceMap = array(
array('action' => 'index', 'method' => 'GET', 'id' => false),
array('action' => 'view', 'method' => 'GET', 'id' => true),
array('action' => 'add', 'method' => 'POST', 'id' => false),
array('action' => 'edit', 'method' => 'PUT', 'id' => true),
array('action' => 'delete', 'method' => 'DELETE', 'id' => true),
array('action' => 'edit', 'method' => 'POST', 'id' => true)
);
The first thing pops out and smells is the double entry for the edit action. This clearly indicates that I’ll need to put in conditional logic to either present the edit view or save a posted edit form. One of those edit methods needs to be changed to an update action to remove the edit conditionals.
There are actions missing from the mapResources as well. Where’s the new(create) action? This presents a view with the fields for creating a new record of whatever. Certainly submitting the form would POST to the add action.
As it stands and as advertised the mapResources does work. /posts calls the index action. /posts/1 calls the view action. So how can the two missing actions (update / new) be added easily?
The original config/routes.php file would look like this:
Router::mapResources('posts');
Just add two lines above the mapResources:
Router::connect("/:controller/:id", array("action" => "update", "[method]" => "PUT"),array('pass' => array('id'));
Router::connect("/:controller/new", array("action" => "create", "[method]" => "GET"));
//Original
Router::mapResources('posts');
As long as those two lines are above any mapped resources they will all act the same. So:
Router::connect("/:controller/:id", array("action" => "update", "[method]" => "PUT"),array('pass' => array('id'));
Router::connect("/:controller/new", array("action" => "create", "[method]" => "GET"));
Router::mapResources('posts')
Router::mapResources('users');
Will apply the new update and create routing for both posts and users.
There is one other thing that is bugging me about the cakePHP RESTFul implementation. The PUT/POST method to call an edit view. I want to be able to call posts/1/edit with a GET to display the edit view. So with one more line of code in the routes.php file.
Router::connect("/:controller/:id/edit", array("action" => "edit", "[method]" => "GET"),array('pass' => array('id'));
Router::connect("/:controller/:id", array("action" => "update", "[method]" => "PUT"),array('pass' => array('id'));
Router::connect("/:controller/new", array("action" => "create", "[method]" => "GET"));
Router::mapResources('posts')
Router::mapResources('users');
Now we have RESTFul routing for these routes!
| URL | Method | Action |
|---|---|---|
| /posts | GET | index() |
| /posts | POST | add() |
| /posts/new | GET | create() |
| /posts/1 | GET | view($id) |
| /posts/1 | PUT | update($id) |
| /posts/1/edit | GET | edit($id) |
| /posts/1 | DELETE | delete($id) |
| /users | GET | index() |
| /users | POST | add() |
| /users/new | GET | create() |
| /users/1 | GET | view($id) |
| /users/1 | PUT | update() |
| /users/1/edit | GET | edit($id) |
| /users/1 | DELETE | delete($id) |
