开发者

Creating canonical URLs with custom route-classes

I'm trying to implement canonical 开发者_高级运维URLs and combine it with custom route-classes.

The URL-scheme is something like this:

/category-x/article/123
/category-y/article/123

I create a custom route-class extending Zend_Controller_Router_Route_Regex and checks that the article 123 exists and that the URL includes the correct category-name. If article 123 belongs in category-x and the user is accessing category-y I want to redirect to the correct URL.

But the routes does not have any obvious possibility to do this directly. What's the best practice approach here?


I often do this in my action controller. Something like this...

// assuming GET /category-y/article/123
// $article->url is generated, and contains /category-x/article/123

if (this->_request->getRequestUri() != $article->url) {
    return $this->_helper->redirector->goToUrl($article->url);
}

In this example, $article->url would need to be generated from your database data. I often use this to verify a correct slug, when I also pull in the object id.

You could also potentially move this to your routing class, if you wanted to use a custom one instead of using Regex (you could subclass it).


I ended up with this solution:

  1. The custom route-class creates the canonical URL in its match()-method like this:

    public function match($path, $partial = false) {
        $match = parent::match($path, $partial);
    
        if (!empty($match)) {
             $article = $this->backend->getArticle($match['articleId']);
    
             if (!$article) {
                 throw new Zend_Controller_Router_Exception('Article does not exist', 404);
             }
    
             $match['canonicalUrl'] = $this->assemble(array(
                 'title' => $article->getTitle(), 
                 'articleId' => $article->getId()
            ));
        }
    
        return $match;
    }
    

    $article is populated inside match() if the parent::match() returns array.

  2. I've created a front controller plugin which hooks on the routeShutdown() like this:

    public function routeShutdown(Zend_Controller_Request_Abstract $request) {
        if ($request->has('canonicalUrl')){
            $canonicalUrl = $request->getBaseUrl() . '/' . $request->get('canonicalUrl');
    
            if ($canonicalUrl != $request->getRequestUri()) {
                $this->getResponse()->setRedirect($canonicalUrl, 301);
            }
        }
    }
    

    It simply checks if the route(custom or native Zend) created a canonical URL and if the requested URL does not match, redirect to the correct canonical URL.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜