带有Rest的子文件夹的Zend Framework路由

时间:2011-12-15 16:34:37

标签: php zend-framework zend-rest zend-router zend-rest-route

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

这是我的结构。

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

在admin子文件夹中调用Controller:

/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集成到这些规则集中。

非常感谢每一个帮助。

1 个答案:

答案 0 :(得分:0)

我已经使用Subclassed多个类来实现此目的,并为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;
    }
}