我正在研究一个'私人'应用程序,您必须登录才能做任何事情。这给了我一点加载Zend Navigation角色的问题。目前,我正在"init"Zend导航在我的引导;在我为Zend Nav添加ACL之前,一切都很好。问题是,我想加载'userRole'从我的认证存储,但不会有存储,直到用户登录,所以这让我一个'试图获得非对象的属性'警告在登录页面。这是因为在登录之前,auth的存储中没有任何内容,因此auth->userRole
为'nothing',因为auth->getInstance()->getIdentity()->???
将为空,直到用户登录并配置auth。
我没有在登录页面使用Zend导航,事实上我有一个登录页面的替代布局(根本没有导航);'if !$auth->hasIdentity'
(假)使用登录布局,只显示登录页面的问题,系统范围内,正如我所说的应用程序是完全私有的,所以默认为"客人"角色或类似的东西,似乎像一个"肮脏"的方法,因为一旦用户登录它将不得不重新配置无论如何认证。仅仅为了取悦登录页面而设置一个通用的认证身份似乎是不对的。
我得到的是,在哪里是一个好地方移动Zend导航的"初始化",或者至少移动配置ACL部分?还是把整件事都搬走吧?
这是我在bootstrap.php中为Zend Navigation设置的内容:
protected function _initNavigation() {
$this->_logger->info('Bootstrap ' . __METHOD__);
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
$container = new Zend_Navigation($config);
$acl = new Application_Model_Acl_Acl();
$role = Zend_Auth::getInstance()->getIdentity()->userRole;
$view->navigation($container)->setAcl($acl)->setRole($role);
}
引导运行时为空(或非对象)的'$role = Zend_Auth::getInstance()->getIdentity()->userRole'
。
我所有的ACL发生在控制器(在动作)或一些可能发生在模型在某个点,虽然我不期望web服务或任何东西,所以也许他们会留在控制器,但我有灵活性,因为我有ACL在模型中(这将是"域",对吗?
我只使用ACL在Zend导航布局,用户体验的目的;根据用户角色,我从Zend导航中获得的菜单和链接将是"灰色",不存在或活动(并且可见),例如,"用户"角色将不会获得许多"admin"选项,这是由控制器中的ACL强制执行的,因此人们不能简单地键入url并进入一个区域。
我的另一个想法是,也许我应该考虑移动我的登录到引导这种情况下,但我不确定这是一个好主意吗?
编辑:
这是我放入Front Controller Plugin的代码:
class Plugins_Controller_ZendNavInit extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
$container = new Zend_Navigation($config);
$acl = new Application_Model_Acl_Acl();
$layout = Zend_Layout::getMvcInstance();
$view = $layout->getView();
$role = Zend_Auth::getInstance()->getIdentity()->userRole;
$view->navigation($container)->setAcl($acl)->setRole($role);
}
}
}
伟大的工作;当然,我必须像其他插件一样注册我的插件。
您可以在登录之前构建一个匿名角色,并为匿名用户处理一个非常短的ACL策略。查看下面的响应,以了解如何使用Auth Plugin在PreDispatch上捕获未经身份验证的用户。
我不会直接从Auth存储中提取它。如果您从Zend_Auth中提取它,并且在用户会话期间用户的角色被更改,那么您将不得不强制注销/登录或更新Zend_Auth存储中的信息。我发现设置Role类并执行逻辑以确定其中的角色或设置默认(来宾)角色更容易。User角色类扩展了我的User模型并实现了Zend_Acl_Role_Interface。然后,我可以从Role类中查询db。我大约一天前开始实现这个,但这里有一个例子:
<?php
类Zfcms_Acl_Role_User扩展Zfcms_Model_Users实现Zend_Acl_Role_Interface{
/**
* Unique id of Role
*
* @var string
*/
protected $_roleId;
public $_inheritsFrom = 'guest';
public $_defaultRole = 'user';
/**
* Sets the Role identifier
*
* @param string $id
* @return void
* Defined by Zend_Acl_Role_Interface; returns the Role identifier
*
* @return string
*/
public function getRoleId()
{
//$auth = Zend_Auth::getInstance();
if(Zend_Auth::getInstance()->hasIdentity())
{
$this->_roleId = self::getUserRoleById(Zend_Auth::getInstance()->getIdentity()->user_id);
return $this->_roleId;
}
elseif(!Zend_Auth::getInstance()->hasIdentity() && !isset($this->role))
{
//return 'guest';
return (string) new Zfcms_Acl_Role_Guest();
} else {
throw new Zend_Controller_Action_Exception('Invalid user roleId', 110);
}
}
public function getDefaultRole()
{
return $this->_defaultRole;
}
public function getPrivsByRole($role)
{
//TODO: Design db table to hold privs
}
private function setPrivs()
{
//TODO: implement
}
/**
* Defined by Zend_Acl_Role_Interface; returns the Role identifier
* Proxies to getRoleId()
*
* @return string
*/
public function __toString()
{
return $this->getRoleId();
}
public function getUserRoleById($id)
{
$this->_id = $id;
$query = $this->select()
->from('users', array('user_id', 'role'))
->where('user_id = ?', $this->_id);
$result = $this->fetchAll($query);
foreach($result as $userRole)
{
$role = $userRole->role;
}
return $role;
}
}