Archive for the ‘cakePHP’ Category

CakePHP RESTFul Resources, Not There Yet.

March 5th, 2009 by ScottK | 3 Comments | Filed in cakePHP

Now 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)

Tags: , , ,

Fail! cakePHP 1.2 model testing with associations

January 20th, 2008 by ScottK | No Comments | Filed in cakePHP

I love to unit test! All the way down to my JavaScript libraries you’ll find a unit test. While some may argue that Behavior Driven Development is better I find that that TDD not only affords me more robust bug free code but also ensures that I am not going off track during development. So with cakePHP 1.2 beta and simpleTest we get a unit test framework for making sure that the code we write is tested prior to production.

Very Cool as that is one judgement I use to determine if the language or framework I am working with will amount to anything, i.e. can it be tested. cakePHP can be tested with SimpleTest and you can load fixtures to make sure your tests are correctly setup for what you need to

However….

With the introductions of associations in cakePHP it fails miserably.  Given that I have a model for a blog post I can write and use all the tests that I need to make sure that it performs exactly as I need it to do and handle all the foreseen exceptions. That was really cool until I added the comment model. The post model has many comments and the comment model belongs to a post. That’s where the problems begin.

The resulting unit test then began to throw exceptions in the tests where looking for test_suite_post_id in the comment table as opposed to post_id. What I mean is that in the comment model that belonged to a single post one field was post_id which was the foriegn key to the post so the model associations would work. In the testing environment however the tests where looking for a field called test_suite_post_id which didn’t exist.

I did find that if you import the database field representation with records => true you would not throw the errors and exceptions. Seriously though it’s using live data from your production database and you have no way to fine grain the exceptions to test your tests.

Certainly one could argue that the fixtures could implement the strange behavior as such but because  the comment fixture test would only load the fixtures for the comment model and not multiple models, I would hope that post_comment fixtures file wouldn’t be necessary (I didn’t even try this) during the setup of the comment test. In this structure there would be a lot of files for testing one model as large sites development.

With cakePHP 1.2 beta we have been presented with a lot of goodness. Testing for associative models still needs some improvement however. I’m not sure if it’s cakePHP or the simpleTest platform for the failure but non-associative testing works just fine.

CakePHP Handles Resources

November 8th, 2007 by ScottK | 1 Comment | Filed in cakePHP

Wow I finally get to read again and it’s been a while so I just found this out. CakePHP 1.2.xx pre-beta now supports mapresources as phpnut says New CakePHP Releases. This is awesome news as Ruby on Rails can use this and we make extensive use of this for RESTful applications. With this announcement I can’t wait for 1.2 to go BETA.

Up to a few weeks ago I was downloading the nightly builds, but the constant development and requirements from Argus became to much to continue working with cake. Once 1.2 goes BETA though watch out!