2010-10-22 142 views
0

我使用的是自定义的路由器,使像网页:如何在Zend-Framework中创建自定义路由器?

mytutorialsite.com/category/:categoryname

# added to application.ini 
resources.router.routes.categorynameOnCategory.route = /category/:categoryname 
resources.router.routes.categorynameOnCategory.defaults.module = default 
resources.router.routes.categorynameOnCategory.defaults.controller = category 
resources.router.routes.categorynameOnCategory.defaults.action = categoryname 

我也有数据库表“类别”中,所有类别的存储。例如,假设有以下几类当前存储在我的数据库:

- html 
- css 
- js 
- php 

这意味着,以下页面存在:

  • mytutorialsite.com/category/html
  • mytutorialsite .com/category/css
  • mytutorialsite.com/category/js
  • mytutorialsite.com/category/php

但是,当你访问一个页面,未在数据库中列出,像一个类别名称:

  • mytutorialsite.com/category/foo

你应该得到404页面不存在消息。

我该如何做到这一点?

回答

1

我认为你的意思是categoryname作为你的路由中的动作:categoryname应该用作一个动作?有两种方法可以使用。首先,您只添加路由到存在类别的路由器。当请求category/foo时,路由器将无法识别路由并抛出404错误。

第二个选项是你捕获所有类别/ *路线,并在你的行动中检查是否存在类别。

对于第一个选项,添加一个带有routeStartup函数的frontController插件。在这个钩子你可以这样做:

public function routeStartup(Zend_Controller_Request_Abstract $request) 
{ 
    // Get the router 
    $router  = Zend_Controller_Front::getInstance()->getRouter(); 

    // Fetch all your categories 
    $category = new Application_Model_Category; 
    $categories = $category->fetchAll(); 

    // Loop and add all individual categories as routes 
    foreach ($categories as $category) { 
     $route = 'category/:' . $category->name; 
     $params = array(
      'module'  => 'default', 
      'controller' => 'category', 
      'action'  => $category->name 
     ); 

     $route = new Zend_Controller_Router_Route($route, $params); 
     $router->addRoute($category->name, $route); 
    } 
} 

另一种方法是更简单的路线。在你的application.ini:

resources.router.routes.category.route  = "category/:action" 
resources.router.routes.category.module  = "default" 
resources.router.routes.category.controller = "category" 

现在从类别中的所有请求/ SOMETHING必去的默认模块,类别控制器。调度员检查动作SOMETHING是否存在。当它发生时,它执行该动作。如果没有,Zend_Controller_Action_Exception(“action does not exist”)就是抛出。

所以简而言之,这两种方法都有效。随着第一个你得到更多的控制。第二种更简单,但当例如categoryController中的editAction,addAction或removeAction存在,它们也可以被触发(所以要小心该方法)。

PS。当然,routeStartup函数应该有一个缓存机制来阻止每个请求上的数据库查询。

+0

谢谢,这是非常有益的! – 2010-10-24 14:53:44

+0

前端控制器插件只有一个问题。现在每个$ category->名称在控制器中都有自己的操作。如果您希望所有类别名称使用相同的categorynameAction,只需更改'action'=>'categoryname'即可。 – 2010-10-24 18:01:58

+0

这是正确的。如果你想将网址路由到所有相同的动作,它就更简单了(参见我的回答顶部的假设)。 路由很简单:“category /:category”,并为该路由添加一个动作(“categoryName”)。然后在categorynameAction中,参数“category”可以通过$ this - > _ getParam(“category”)获得。 – 2010-10-24 18:09:00