Q : How can I show display different menu(s) by user role?
Description : the app has many roles. e.g HR manager, Account Manager, Operating Manager, Employee, Operator, ...., etc. I used rights and yii-user modules to create those roles. Those roles have different functions. So the app will show different menu for different user's role after logged in. Now, I can lock the function for different user. e.g when HR manger logged in, he/she can't route to other function of user role. But I don't know how to show the HR Menu for Hr Manager, only.
I am not a newbie for yii. but I'm a newbie for those modules (rihgts and yii-user).
If you're using RBAC you can set the 'visible' param of CMenu items depending on the users privileges, for example;
$this->widget('zii.widgets.CMenu',array(
'items'=>array(
array(
'label'=>'Home',
'url'=>array('site/index'),
),
array(
'label'=>'HR',
'url'=>array('/hr/index'),
'visible'=>Yii::app()->user->checkAccess('hr')
),
array(
'label'=>'Accounts',
'url'=>array('/account/index'),
'visible'=>Yii::app()->user->checkAccess('account')
),
array(
'label'=>'Operations',
'url'=>array('/operations/index'),
'visible'=>Yii::app()->user->checkAccess('operations')
),
),
);
This way users will only be able to see the items in the menu if they have access privileges for that area.
[EDIT]
As per simaremare's comment below, you can force caching of this query beyond the current request by extending CWebUser
. Firstly, set your user to run through your new class (we'll call it TWebUser
), so in your main.php config file;
'components'=>array(
'user'=>array(
...
'class'=>'TWebUser',
...
),
...
),
Now we need to create TWebUser
to cache these beyond the current request (which is what CWebUser
does (source code):
class TWebUser extends CWebUser
{
private $_access=array();
public function checkAccess($operation,$params=array(),$allowCaching=true)
{
if($allowCaching && $params===array() && isset($this->_access[$operation]))
return $this->_access[$operation];
$cache = Yii::app()->session['checkAccess'];
if($allowCaching && !$this->getIsGuest() && isset($cache[$operation]) && time() - $cache[$operation]['t'] < 1800)
{
$checkAccess = $cache[$operation]['p'];
} else {
$checkAccess = Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params);
if($allowCaching && !$this->getIsGuest())
{
$access = isset($cache) ? $cache : array();
$access[$operation] = array('p'=>$checkAccess, 't'=>time());
Yii::app()->session['checkAccess'] = $access;
}
}
return $this->_access[$operation] = $checkAccess;
}
}
Now your access results will be set for the whole session. This does mean that if you edit the RBAC permissions for a given account, they'll have to log out and log in again to see the new changes reflected in the browser.
I hope that helps! I'm sure I found this workaround from someone else (probably on SO), but I can't find the original post to give them credit.