Zend框架路由的子文件夹与Rest



对于我当前的应用程序设置,我正在尝试为标准控制器和Rest控制器创建路由。

这是我的结构。

/application
  /modules
    /module
      /controllers
        /Admin
        /Api

调用admin子文件夹中的控制器:

/module/admin_controller/action

我想把这个改成:

/admin/module/controller/action

在我当前的设置中:

/* application.ini */
;Default route
resources.router.routes.defaultmodule.type = Zend_Controller_Router_Route_Module
resources.router.routes.defaultmodule.defaults.module = "default

; APi route
resources.router.routes.api.type = Zend_Controller_Router_Route
resources.router.routes.api.route = ":api" 
resources.router.routes.api.reqs.api = "api"
resources.router.routes.apichain.type = Zend_Controller_Router_Route_Chain
resources.router.routes.apichain.chain = "api, defaultmodule"
; Admin route
resources.router.routes.admin.type = Zend_Controller_Router_Route
resources.router.routes.admin.route = ":admin" 
resources.router.routes.admin.reqs.admin = "admin"
resources.router.routes.adminchain.type = Zend_Controller_Router_Route_Chain
resources.router.routes.adminchain.chain = "admin, defaultmodule"

/* Plugin */
class Pwb_Plugin_ControllerRoute
    extends Zend_Controller_Plugin_Abstract
{    
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        if ($request->getParam('admin')) {
            $admin_controller = $request->getParam('admin') . '_' . $request->getControllerName();
            $request->setControllerName($admin_controller);
        }
        if ($request->getParam('api')) {
            $admin_controller = $request->getParam('api') . '_' . $request->getControllerName();
            $request->setControllerName($admin_controller);
        }
    }
}
/* Module Bootstrap */
class Acl_Bootstrap
    extends Zend_Application_Module_Bootstrap
{
    protected function _initRestRoute()
    {
        $this->bootstrap('frontController');
        $frontController = Zend_Controller_Front::getInstance();
        $restRoute = new Zend_Rest_Route(
                $frontController,
                array(),
                array(
                    'acl' => array(
                        'api_role'
                    ))
        );
        $frontController->getRouter()->addRoute('restAcl', $restRoute);
    }
}

这里的问题是API文件夹中的一些控制器是Rest的,但不是全部。

/api/acl/role正确路由到indexAction

/api/acl/role/1正在寻找动作"1",我希望它路由到getAction。

如何将模块Bootstrap中的Zend_Route_Rest集成到这些规则集中?

我已经子类化了多个类来实现这一点,并为admin/api创建了静态路由

Application Bootstrap
protected function _initRoute()
    {
        $front = Zend_Controller_Front::getInstance();
        $router = $front->getRouter();
        $dispatcher = $front->getDispatcher();
        $request = $front->getRequest();
        $defaultRoute = new Pwb_Controller_Router_Route_Module(array(), $dispatcher, $request);
        //Replace default route in our router with our own route
        $router->addRoute('default', $defaultRoute);

        $adminRoute = new Pwb_Controller_Router_Route(
                ':admin',
                array(),
                array(
                    'admin' => 'admin'
                )
        );
        $adminDefault = $adminRoute->chain($defaultRoute);
        $router->addRoute('admin', $adminRoute);
        $router->addRoute('admin', $adminDefault);
        $apiRoute = new Pwb_Controller_Router_Route(
                ':api',
                array(),
                array(
                    'api' => 'api'
                )
        );
        $apiDefault = $apiRoute->chain($defaultRoute);
        $router->addRoute('api', $apiDefault);
        $router->addRoute('api', $apiRoute);
    }

Rest Route
class Pwb_Controller_Router_Rest extends Zend_Rest_Route
{ 
    public function match($request, $partial = false)
    {
        if (!$request instanceof Zend_Controller_Request_Http) {
            $request = $this->_front->getRequest();
        }
        $this->_request = $request;
        $this->_setRequestKeys();
        $path   = $request->getPathInfo();
        $params = $request->getParams();
        $values = array();
        $path   = trim($path, self::URI_DELIMITER);
        if ($path != '') {
            $path = explode(self::URI_DELIMITER, $path);
            //Determine Environment
            if($path[0] != 'api') {
                return false;
            } else {
                array_shift($path);
            }
            // Determine Module
            $moduleName = $this->_defaults[$this->_moduleKey];
            $dispatcher = $this->_front->getDispatcher();
            if ($dispatcher && $dispatcher->isValidModule($path[0])) {
                $moduleName = $path[0];
                if ($this->_checkRestfulModule($moduleName)) {
                    $values[$this->_moduleKey] = array_shift($path);
                    $this->_moduleValid = true;
                }
            }
            // Determine Controller
            $controllerName = $this->_defaults[$this->_controllerKey];
            if (count($path) && !empty($path[0])) {
                if ($this->_checkRestfulController($moduleName, 'api_' . $path[0])) {
                    $controllerName = 'api_' . $path[0];
                    $values[$this->_controllerKey] = 'api_' . array_shift($path);
                    $values[$this->_actionKey] = 'get';
                } else {
                    // If Controller in URI is not found to be a RESTful
                    // Controller, return false to fall back to other routes
                    return false;
                }
            } elseif ($this->_checkRestfulController($moduleName, $controllerName)) {
                $values[$this->_controllerKey] = $controllerName;
                $values[$this->_actionKey] = 'get';
            } else {
                return false;
            }
            //Store path count for method mapping
            $pathElementCount = count($path);
            // Check for "special get" URI's
            $specialGetTarget = false;
            if ($pathElementCount && array_search($path[0], array('index', 'new')) > -1) {
                $specialGetTarget = array_shift($path);
            } elseif ($pathElementCount && $path[$pathElementCount-1] == 'edit') {
                $specialGetTarget = 'edit';
                $params['id'] = urldecode($path[$pathElementCount-2]);
            } elseif ($pathElementCount == 1) {
                $params['id'] = urldecode(array_shift($path));
            } elseif ($pathElementCount == 0 && !isset($params['id'])) {
                $specialGetTarget = 'index';
            }
            // Digest URI params
            if ($numSegs = count($path)) {
                for ($i = 0; $i < $numSegs; $i = $i + 2) {
                    $key = urldecode($path[$i]);
                    $val = isset($path[$i + 1]) ? $path[$i + 1] : null;
                    $params[$key] = urldecode($val);
                }
            }
            // Determine Action
            $requestMethod = strtolower($request->getMethod());
            if ($requestMethod != 'get') {
                if ($request->getParam('_method')) {
                    $values[$this->_actionKey] = strtolower($request->getParam('_method'));
                } elseif ( $request->getHeader('X-HTTP-Method-Override') ) {
                    $values[$this->_actionKey] = strtolower($request->getHeader('X-HTTP-Method-Override'));
                } else {
                    $values[$this->_actionKey] = $requestMethod;
                }
                // Map PUT and POST to actual create/update actions
                // based on parameter count (posting to resource or collection)
                switch( $values[$this->_actionKey] ){
                    case 'post':
                        if ($pathElementCount > 0) {
                            $values[$this->_actionKey] = 'put';
                        } else {
                            $values[$this->_actionKey] = 'post';
                        }
                        break;
                    case 'put':
                        $values[$this->_actionKey] = 'put';
                        break;
                }
            } elseif ($specialGetTarget) {
                $values[$this->_actionKey] = $specialGetTarget;
            }
        }
        $this->_values = $values + $params;
        $result = $this->_values + $this->_defaults;
        if ($partial && $result)
            $this->setMatchedPath($request->getPathInfo());
        return $result;
    }
}
Module Bootstrap;
class Acl_Bootstrap
    extends Zend_Application_Module_Bootstrap
{
    protected function _initRestRoute()
    {
        $this->bootstrap('frontController');
        $frontController = Zend_Controller_Front::getInstance();
        $restRoute = new Pwb_Controller_Router_Rest(
                $frontController,
                array(),
                array(
                    'acl' => array(
                        'api_role'
                    ))
        );
        $frontController->getRouter()->addRoute('restAcl', $restRoute);
    }
}

class Pwb_Controller_Router_Route_Module extends Zend_Controller_Router_Route_Module
{
    public function match($path, $partial = false)
    {
        $return =  parent::match($path, $partial);
        $front = Zend_Controller_Front::getInstance();
        $request = $front->getRequest();
        $is_admin_env = $request->getParam('is_admin_env');
        if($is_admin_env) {
            $return['controller'] = $is_admin_env . '_' .  $return['controller'];
        }
        return $return;
    }
}
class Pwb_Controller_Router_Route extends Zend_Controller_Router_Route
{
    public function match($path, $partial = false) {
        $return = parent::match($path, $partial);
        if(isset($return['admin'])) {
            $front = Zend_Controller_Front::getInstance();
            $request = $front->getRequest();
            $request->setParam('is_admin_env', $return['admin']);
            $front->setRequest($request);
        }
        return $return;
    }
}

最新更新