使用Zend_Controller_Route根据用户角色自动确定控制器:如何?

时间:2010-10-06 14:03:48

标签: php zend-framework routes

我目前正在想办法解决上述问题。

我目前的申请结构如下:

/modules
 / modulename
  /controllers
    /ProjectController.php

该应用程序有3个不同的用户角色,每个角色都包含在这些模块中。我想防止在一个控制器中为每个用户角色执行多个操作,因为我认为它使我的代码不那么可读和丑陋。所以,我在考虑这样的结构:

/modules
 / modulename
  /controllers
    /ProjectController.php
    /EmployeeProjectController.php
    /ExecutiveProjectController.php

这应该如下工作:

  • 应为管理员用户
  • 加载Projectcontroller.php
  • 应为员工加载EmployeeProjectController.php
  • 应为高管们加载ExecutiveProjectController.php

当然,我可以比较容易地为每个用户角色提供不同的URL方案,但我不想要这个。我想要一个统一的URL方案。

然后,下一步是为每个控制器创建路由,将它们重写到另一个控制器。 我也想阻止它。

我想要一种全局告诉路由器根据用户角色为控制器添加“执行”或“员工”或其他内容的方法。

最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

听起来你可以使用front controller pluginrouteStartup()方法检查Zend_Auth实例并添加特定于角色的路由(例如,来自INI或XML文件)。 / p>

这样的事情:

class My_Controller_Plugin_RouteByAuth extends Zend_Controller_Plugin_Abstract
{
    public function routeStartup()
    {
        $auth = Zend_Auth::getInstance();
        if (!$auth->hasIdentity()){
            return;
        }
        $identity = $auth->getIdentity();
        if ($identity->isAdmin()){
            $this->_addRoutes('routes_admin.ini');
        } else if ($identity->isEmployee()){
            $this->_addRoutes('routes_employee.ini');
        } else if ($identity->isExecutive()){
            $this->_addRoutes('routes_executive.ini');
        } else {
            return;
        }
    }

    protected function _addRoutes($file)
    {
        $front = Zend_Controller_Front::getInstance();
        $router = $front->getRouter();
        $routes = new Zend_Config_Ini(APPLICATION_PATH . '/configs/ ' . $file);
        $router->addConfig($routes);
    }
}

未经测试,但我希望这传达了一个可行的想法的核心。

答案 1 :(得分:1)

我花了很多时间弄清楚如何使用Zend_Controller_Router_Route来做这件事,并提出了可行的解决方案:

class App_Controller_Router_Route_Rolebasedcontroller extends Zend_Controller_Router_Route_Module
{
    /**
     * Roles that should be rewritten automatically
     * 
     * @var array
     */
    protected $_rewriteRoles = array('employee', 'executive');

    /**
     * Matches a user submitted path. Assigns and returns an array of variables
     * on a successful match.
     *
     * If a request object is registered, it uses its setModuleName(),
     * setControllerName(), and setActionName() accessors to set those values.
     * Always returns the values as an array.
     *
     * @param string $path Path used to match against this routing map
     * @return array An array of assigned values or a false on a mismatch
     */ 
    public function match($path, $partial = false)
    {
        $result = parent::match($path, $partial);

        $role = Plano_Acl::getInstance()->getCurrentRole();

        if (null !== $role && in_array($role, $this->_rewriteRoles))
        {
            if (isset($result[$this->_controllerKey]))
            {
                $result[$this->_controllerKey] = $role . ucfirst($result[$this->_controllerKey]);
            }
        }

        return $result;
    }

    /**
     * Assembles user submitted parameters forming a URL path defined by this route
     * Removes fole prefixes when required
     *
     * @param array $data An array of variable and value pairs used as parameters
     * @param bool $reset Weither to reset the current params
     * @return string Route path with user submitted parameters
     */
    public function assemble($data = array(), $reset = false, $encode = true, $partial = false)
    {
        if (!$this->_keysSet) {
            $this->_setRequestKeys();
        }

        $params = (!$reset) ? $this->_values : array();

        foreach ($data as $key => $value) {
            if ($value !== null) {
                $params[$key] = $value;
            } elseif (isset($params[$key])) {
                unset($params[$key]);
            }
        }

        $params += $this->_defaults;

        $url = '';

        if ($this->_moduleValid || array_key_exists($this->_moduleKey, $data)) {
            if ($params[$this->_moduleKey] != $this->_defaults[$this->_moduleKey]) {
                $module = $params[$this->_moduleKey];
            }
        }
        unset($params[$this->_moduleKey]);

        $controller = $params[$this->_controllerKey];

        // remove role prefix from url when required
        $role = Plano_Acl::getInstance()->getCurrentRole();
        if (null !== $role && in_array($role, $this->_rewriteRoles))        
        {
            if (substr($params[$this->_controllerKey], 0, strlen($role)) == $role)
            {
                $controller = lcfirst(substr($params[$this->_controllerKey], strlen($role)));
            }
        }

        unset($params[$this->_controllerKey]);

        $action = $params[$this->_actionKey];
        unset($params[$this->_actionKey]);

        foreach ($params as $key => $value) {
            $key = ($encode) ? urlencode($key) : $key;
            if (is_array($value)) {
                foreach ($value as $arrayValue) {
                    $arrayValue = ($encode) ? urlencode($arrayValue) : $arrayValue;
                    $url .= '/' . $key;
                    $url .= '/' . $arrayValue;
                }
            } else {
                if ($encode) $value = urlencode($value);
                $url .= '/' . $key;
                $url .= '/' . $value;
            }
        }

        if (!empty($url) || $action !== $this->_defaults[$this->_actionKey]) {
            if ($encode) $action = urlencode($action);
            $url = '/' . $action . $url;
        }

        if (!empty($url) || $controller !== $this->_defaults[$this->_controllerKey]) {
            if ($encode) $controller = urlencode($controller);
            $url = '/' . $controller . $url;
        }

        if (isset($module)) {
            if ($encode) $module = urlencode($module);
            $url = '/' . $module . $url;
        }

        return ltrim($url, self::URI_DELIMITER);
    }   
}