Adding The Post's Title To The URL

Adding the post's title to the URL has multiple advantages. It allows the user to see where the URL is pointing to and search engines will improve your ranking.

The first thing we need to do is adapt our routing rules to allow for a second parameter in the URL. We'd like the title to be an optional part and we'll restrict it to word-chars and dashes only:

<route name=".post" pattern="^/(post:\d+)(-{title:[-\w]+})?" action="Post">
  <route name=".show" pattern="^$" action=".Show" />
</route>

Now that we made it possible to inject the title we just need to adapt the places where we generate the URLs to actually pass the title. Currently this is only in the Posts_IndexSuccessView [app/modules/Posts/views/IndexSuccessView.class.php], so let's change that. Remember that we only allowed word chars in the route, so we need to make shure that we only pass word chars in - we'll just replace anything that's not a word char by a dash:

<?php

class Posts_IndexSuccessView extends BlogPostsBaseView
{
  
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd);
    $ro = $this->getContext()->getRouting();

    $this->setAttribute('_title', 'Latest Posts');
    
    
    $posts = array();
    
    foreach($this->getAttribute('posts') as $p)
    {
      $post = $p->toArray();
      $post['url'] = $ro->gen(
        'posts.post.show', 
        array(
          'post' => $p->getId(), 
          'title' => preg_replace('/\W/', '-', $p->getTitle())
        )
      );
      
      $posts[] = $post;
    }
    
    $this->setAttribute('posts', $posts);
  }
}

?>

Hmm. That works, but it might get a bit tedious to always remember that if you generate the URL to a post, you'll have to pass in the post-id and the title and replace all non-word chars by dashes. Well, surprise, there's a better way.