Search code examples
phpcakephproutesseocanonical-link

CakePHP routing multilingual blog with canonical links


I have the following routes set up on my CakePHP site

Router::connect('/:language/blog', array('controller' => 'posts', 'action' => 'index'), array('language' => 'en', 'persist'=>array('language')));

Router::connect('/:language/blogue', array('controller' => 'posts', 'action' => 'index'), array('language' => 'fr', 'persist'=>array('language')));

Router::connect('/:language/blog/:post_id', array('controller' => 'posts', 'action' => 'view'), array('language' => 'en', 'persist'=>array('language', 'post_id')));

Router::connect('/:language/blog/:post_id/:slug', array('controller' => 'posts', 'action' => 'view'), array('language' => 'en', 'persist'=>array('language', 'post_id', 'slug')));

Router::connect('/:language/blogue/:post_id', array('controller' => 'posts', 'action' => 'view'), array('language' => 'fr', 'persist'=>array('language', 'post_id')));

Router::connect('/:language/blogue/:post_id/:slug', array('controller' => 'posts', 'action' => 'view'), array('language' => 'fr', 'persist'=>array('language', 'post_id', 'slug')));

Which gives me URLs like /en/blog or /fr/blogue Is there a way to remove the language from appearing in the URL and have it just display /blog or /blogue (but still persist the language param)?

If that's not possible I can probably live with keeping the language in the url however this next bit is really important. I have something like this in my <head>

echo '<link rel="canonical" href="'. Router::url($this->request->here true) .'">';

where I'd like to include a canonical URL for SEO. I'd like the canonical URL to be simply /blog/123 but it is always showing as whatever the current url is ie. /en/blog/123/article-slug or /fr/blogue/123/article-slug. Does anyone know how I can get the desired behavior? (side question: does removing the slug part from the canonical url defeat the purpose of using friendly URLs for SEO?)


Solution

  • I solved it by changing my routes to these

    Router::connect('/blog', array('controller' => 'posts', 'action' => 'index', 'language'=>'en'), array('persist'=>array('language')));
    Router::connect('/blog/:post_id', array('controller' => 'posts', 'action' => 'view', 'language'=>'en'), array('persist'=>array('language', 'post_id')));
    Router::connect('/blog/:post_id/:slug', array('controller' => 'posts', 'action' => 'view', 'language'=>'en'), array('persist'=>array('language', 'post_id', 'slug')));
    
    Router::connect('/blogue', array('controller' => 'posts', 'action' => 'index', 'language'=>'fr'), array('persist'=>array('language')));
    Router::connect('/blogue/:post_id', array('controller' => 'posts', 'action' => 'view', 'language'=>'fr'), array('persist'=>array('language', 'post_id')));
    Router::connect('/blogue/:post_id/:slug', array('controller' => 'posts', 'action' => 'view', 'language'=>'fr'), array('persist'=>array('language', 'post_id', 'slug')));
    

    and in my Posts controller View action I added

    $this->set('canonical', Router::url(array('controller'=>'posts', 'action'=>'view', 'post_id'=>$post['Post']['id'], 'language'=>'en')));
    

    And in the <head> section of my layout file I added

    if (!isset($canonical)) {
        $canonical = $this->request->here;
    }
    if ($canonical !== false) {
        echo '<link rel="canonical" href="'. Router::url($canonical, true) .'">';
    }