Tip: use CakePHP Route::url() for your URLs

Routing is one of the amazing features of CakePHP because it makes the urls beautiful. We use this most of the time and last time, I blogged about the helper to shortcut ones typing when using the HTML helper. Overtime, I realize how helpful it can be. Read on.

Always use array when passing parameters when creating a link or using Router::url(), it will save you time in the future. Why? Consider this scenario:

You created a controller /users/register and in your code and you added this

link('User Registration', '/users/register')?>

Then your group or your boss decided to use a better name /register. Your initial thought would be to replace all those texts to those new ones, isn’t it? There is a better approach. Try the ffg:

In /config/router.php

'users','action'=>'register'));  ?>

In your view:

link('Registration', array('controller'=>'users','action'=>'register'))?>

the HTML helper uses Router::url() in its link function and the Router class magically converts array parameters to what you stated in your config. In writing urls, we have to be consistent because it can be bad for SEO when you have too many urls pointing to the same location.

Although the above works beautifully but it can be a tedious job. I wrote not long ago about the html helper that could make this approach easier so you could write the ffg in your view.

link('Registration', url( 'users', 'register', null, 'teacher' ))?>

It saves a few characters!

From the last post, I refactored it and placed it in the bootstrap so I can call it anywhere (got that idea from the google groups).

Here it is:

    function url() {
        $args = func_get_args();
        $count = func_num_args();

        if ( $count == 1 ) {
            if ( is_array( $args[0] ) ) {
                $args = $args[0];
                $count = count($args);
            } else {
                return $args[0];
            }
        }

        $short_keys = array(
            0 => 'controller',
            1 => 'action',
            2 => 'plugin',
            'c' => 'controller',
            'a' => 'action',
            'p' => 'plugin',
        );

        foreach ( $short_keys as $short_name => $long_name ) {

            if ( isset( $args[$short_name] ) ) {
                $args[$long_name] = $args[$short_name];
                unset( $args[$short_name] );
            }

        }

        // Need to explicitly assign plugin key
        if ( !isset( $args['plugin'] ) ) $args['plugin'] = null;
        if ( !isset( $args['action'] ) ) $args['action'] = 'index';
        if ( !isset( $args['admin'] ) ) $args['admin'] = false;

        $routing = Configure::read('Routing.admin');
        if ( preg_match( "/^{$routing}_/", $args['action'] ) && $routing ) {
            $args['admin'] = true;
            $args['action'] = substr( $args['action'], strlen($routing) + 1 );
        }

        return $args;
    }

The function above could take an array OR any number of string parameters.

url ( 'controller', 'action', 'plugin_name', ...[more params here] )
url ( array( 'c' => 'controller', 'a' => 'action', 'p' => 'plugin' ) )

The first one is strict for the first 3 parameters. The latter can be written in any order as you like. I also added support for prefix routing such as admin_*. So you can write:

url ( 'controller', 'admin_action', 'plugin_name', ...[more params here] )
url ( array( 'c' => 'controller', 'a' => 'admin_action', 'p' => 'plugin' ) )

Router::parse() can also be used instead of url() function but the latter is faster.

That’s it. Happy Baking!

Tags: ,

One Response to “Tip: use CakePHP Route::url() for your URLs”

  1. tascalepretle Says:

    It’s amazing

Add Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>