Permanent appended named parameters in routes with CakePHP

For a project i’m working on i needed a bit of custom routing.
Basically the project is a shop where you can edit multiple events and i stored the current event in a session.
But the request came if the client could edit multiple events at the same time.
Long story short, i needed the event_id somewhere in the url and this is where the router comes in to play.

There are a couple of ways to get the event_id in the url with custom routing.

Option one

Use a named parameter

this method will append event_id:[UUID] to the url.
for example: http://www.example.com/products/index/event_id:490ed5ab-ed6c-4034-8205-0264d5453078

in /app/config/routes.php

Router::connectNamed(array('event_id'=>$UUID), array('default' => true, 'greedy' => false));

This will let the router know that we have a named part called event_id.
It will also check if event_id is an UUID (other possibilities are $ID, $day, $month and $year, or a regular expression).

Helper

This was the easy part, because you need to tell all the helpers that create an url to use ‘event_id’=>’[UUID]‘.
In my case i already wrote an app and i didn’t feel like rewriting all links and forms, so i created a file called app_helper.php in the app folder like so:

/app/app_helper.php

<?php
class AppHelper extends Helper { 
        function url($url = null, $full = false) { 
                if (is_array($url)) { 
                        if (empty($url['event_id']) && isset($this->params['named]['event_id'])) { 
                                $url['event_id'] = $this->params['named]['event_id']; 
                        }
                } 
                return parent::url($url, $full); 
        } 
} 
?>

What this does is append the event_id to all url arrays and then calls the parent url function (in /cake/lib/helper/helper.php).
Because all helpers extend AppHelper, all url calls will go tough the above function.

Redirect

Now we only need to address one more issue, namely the $this->redirect(); function in the controllers, because we want the event_id appended to those url’s too.

/app/app_controller.php

function redirect($url, $status = null, $exit = true) { 
 	if (is_array($url)) { 
        if (empty($url['event_id']) && isset($this->params['named]['event_id'])) { 
        	$url['event_id'] = $this->params['named']['event_id']; 
        }
 	}
    return parent::redirect($url, $status, $exit); 
}

All controllers extend app_controller so they will all use this new redirect function.

So once you add event_id:[UUID] to an url, it will always be appended.
the event id can be retrieved in all controllers by calling $this->params['named']['event_id'] or $this->passedArgs['event_id']

Option two

The other way to do this is by changing a lot of routes in the routes.php file, but the url will be prettier (like: http://www.example.com/event_id/controller/action/params)

(/app/config/routes.php)

/*
	 * The following section is to add the event_id to each backend url
	 * The event_id is added in the url method of app_helper.php and redirect method of app_model.php
	 */
	Router::connect('/:event_id/:controller', 
			array('controller'=>':controller'), array('event_id'=>$UUID));

	Router::connect('/:event_id/:controller/:action', 
			array('controller'=>':controller', 'action'=>':action'), array('event_id'=>$UUID));

	Router::connect('/:event_id/:controller/:action/:id', 
			array('controller'=>':controller', 'action'=>':action', 'id'=>':id'), array('pass'=>array('id'),'event_id'=>$UUID));

	Router::connect('/:event_id/:controller/:action/:id/*', 
			array('controller'=>':controller', 'action'=>':action', 'id'=>':id'), array('pass'=>array('id'), 'event_id'=>$UUID));

	Router::connect('/:event_id/:controller/:action/*', 
			array('controller'=>':controller', 'action'=>':action'), array('event_id'=>$UUID));

I’m not shure if this is the most efficient way to cover all routes, but if you replace the code from the first block with this code, you get the nice url (http://www.example.com/event_id/controller/action/params).

The last array makes shure only uuid’s are used by the router.

Filed Under: News - read on

This week in Cake (Part 3)

The nuts and bolts of CakePHP blog started a series about the always tricky HABTM (Has And Belongs To Many) relationships in Cake. If you don’t completely understand the workings of a HABTM releationship head over to Notes on CakePHP HABTM (Part 1, the basics)

On the cakeForge snippets section there are a lot of scripts for creating thumbnails of images. Blognol.com has written a post about just that thing. If you don’t like any of the CakeForge snippets, head over to create thumbnails using cakePHP.

Chris Hartjes asks the question why you wouldn’t want to use Namespaces in CakePHP. If you want to know what he thinks read it at Namespaces in PHP? Why *wouldn’t* you want them?

Peter Butler of Studio Canario has written a post about CakePHP Containable Behavior where he has a real world example of the behavior to better explain the workings of it. check it out at CakePHP Containable Behavior

That’s it for this week, if you have any questions, use the comments form or talk to me in the always busy #cakePHP channel on irc.freenode.net

I’ll post again next week (and maybe even throw in an actual post about using cake ;)). Until then, Happy Baking!

[edit] Fixed link to containable behavior, tanks to RainChen[/edit]

Filed Under: News - read on

Getting real

I’m getting real met het boek van de heren achter 37 signals.com. Ik ben benieuwd wat ik er van ga vinden!

Getting real

Filed Under: Nederlands, News, Personal - read on

Pink for October

De site ziet er iets anders uit dan normaal, dit komt omdat het deze maand de “Pink for October” maand is. In deze maand wordt aandacht gevraagd voor (borst)kanker. Als teken van support zal matsimitsu deze maand alleen in roze verkrijgbaar zijn ;).

Wil je zelf ook meedoen, ga dan naar de pink for October website en kijk hoe jij kan helpen.

Pink for October

Foto: Krazydad

Filed Under: News - read on

Layer tennis

Layer tennis is een spel waarin twee mensen, of groepen van mensen met verschillende Adobe applicaties in real-time een battle aan gaan. Het is de bedoeling om de ander steeds te overtroeven met een beter stuk, wat overigens wel te maken moet hebben met het vorige stuk. Er mag maximaal 15 minuten over een volley gedaan worden, waarna de ander aan de beurt is.

Het is erg gaaf om te kijken wat er van gebakken wordt, een aanrader om te volgen! Vandaag zijn Shaun Inman en Kevin Cornell tegen elkaar aan het strijden, bekijk de match op: layertennis.com

We’re just about ready to roll with Layer Tennis and we’re sure you’re going to find that it has been worth the wait. If you are going to be screwing around on Friday afternoons this Fall (and who isn’t?) make sure you’re screwing around somewhere with high-speed web access.

Filed Under: Nederlands, News - read on