Working with route elements

Even when GET and named parameters can be useful in most situations, we may need to further optimize our application URLs for better search engine rankings.

Fortunately, CakePHP provides us with route elements, a solution that maintains the flexibility of GET and named parameters, and improves the way intra-application URLs are built.

Getting ready

We need some sample data to work with. Follow the Getting ready section of the recipe Using GET and named parameters.

How to do it...

  1. We want our article URLs to be further optimized for search engines, so we start by creating a new route. Edit your app/config/routes.php file and add the following route at the end of the file:
    Router::connect('/article/:category/:id-:title',
    array('controller' => 'articles', 'action' => 'view'),
    array(
    'pass' => array('id'),
    'id' => 'd+',
    'category' => '[^-]+',
    'title' => '[^-]+'
    )
    );
    
  2. As our route defines three elements (id, category, and title), we need to modify the view to specify the values for those elements. Edit your app/views/articles/index.ctp view file and make the following changes:
    <h1><?php echo $article['Article']['title']; ?></h1>
    <p><?php echo $article['Article']['body']; ?></p>
    <?php if (!empty($articles)) { ?>
    <br /><p>Related articles:</p>
    <ul>
    <?php foreach($articles as $related) { ?>
    <li><?php echo $this->Html->link(
    $related['Article']['title'],
    array(
    'action'=>'view',
    'id' => $related['Article']['id'],
    'category' => strtolower(Inflector::slug($related['Category']['name'])),
    'title' => strtolower(Inflector::slug($related['Article']['title']))
    )
    ); ?></li>
    <?php } ?>
    </ul>
    <?php } ?>
    

How it works...

CakePHP uses the routes defined in the routes.php configuration file to generate URLs, and parse requested URLs. When we want different URLs than those provided by the framework, we add new routes to this configuration file.

Routes are created by specifying up to three arguments when calling the Router::connect() method:

  • The first argument is the route URL, a string representation of our route. It can include a wildcard and route elements.
  • The second argument is utilized to specify the default route values, an array which may include plugin, controller, action, and action arguments. You may omit parts of these default values, for example, to define a route for all actions in a specific controller.
  • The third argument defines the route elements, an optional array that defines the route elements a route utilizes. It may also include a list of those elements that are to be sent as arguments when calling the controller action

Using Router::connect(), we defined a route that includes all these arguments:

  • We set /article/:category/:id-:title as our route URL. Notice how we are referring to route elements by prefixing their names with a colon.
  • In the second argument, we specify that this route will match any link to the view action of the articles controller. Similarly, if a URL that matches the route URL specified in the first argument is requested, this is the action that will be executed.
  • We specify three route elements in the third argument, with their respective regular expression matching expressions: id (a number), category (any string that does not include a dash), and title (also a string that does not include a dash.) We use the special pass option to specify which route elements are passed as regular action arguments.

When CakePHP finds a URL that includes the same default values as those specified in the first argument of our route, and also includes the route elements specified in its third argument, it will convert the route to our provided string representation. For example, if we create a link using the following statement:

<?php echo $this->Html->link(
'My article',
array(
'controller' => 'articles',
'action' => 'view',
'id' => 1,
'category' => 'my_category',
'title' => 'my_title'
)
); ?>

We would be matching all our route requirements, and the resulting generated URL would look like http://localhost/article/my_category/1-my_title.

There's more...

When our controller action is executed as a result of a route that uses route elements, we can obtain the values for all the specified elements using the $this->params array available to every controller.

In our example, we set the id route element to be passed as a regular action argument, but we did not do so for the remaining elements (category and title.) To obtain the given value for category, we would do:

$category = $this->params['category']

Using reverse routing

Even though CakePHP allows us to specify a string-based URL when creating links, it is recommended that we always use arrays to define link URLs unless the URL is an absolute reference to a foreign site.

URLs that are defined using an array allow for the reverse routing system to work, which is the part of the framework that allows us to use custom routes.

See also

  • Adding catch-all routes for profile pages
  • Using GET and named parameters
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.118.229