Rbac - No role with name ... could be found

$roles = ['user', 'admin'];
$permissions = [
	'user' => 'view',
	'admin' => 'edit',
];
$hierarchy = [
	'user' => [],
	'admin' => ['user'],
];


$rbac = new Rbac();
$rbac->setCreateMissingRoles(TRUE); // not work in any case

foreach ($roles as $role) {
	$rbacRole = new Role($role);
	$rbacRole->addPermission($permissions[$role]);

	// add roles hierarchy recursive
	foreach ($hierarchy[$role] as $parent) {
		$rbacRole->addParent(new Role($parent));
	}

	$rbac->addRole($rbacRole);
}

$userRole = new Role('user');
var_dump($rbac->isGranted($userRole, 'view'));

We have several roles, permissions & roles hierarchy. First we load all them into RBAC class. Second, we try to take current user role & check if he can do something. But the code above give me No role with name "user" could be found. Why?

Hello and welcome to the forums! :smiley:

This is the correct behaviour. Please see the following examples:

$rbac = new Laminas\Permissions\Rbac\Rbac();

$userRole = new Laminas\Permissions\Rbac\Role('user');
$rbac->addRole($userRole);

var_dump($rbac->hasRole('user')); // true
var_dump($rbac->hasRole($userRole)); // true

$anotherRoleWithSameName = new Laminas\Permissions\Rbac\Role('user');
var_dump($rbac->hasRole($anotherRoleWithSameName)); // false

The difference:

$userRole !== $anotherRoleWithSameName

See also:

Thank you! :grinning:

Understand. It is some strange behaviour, but ok. New code:

$roles = ['user', 'admin'];
$permissions = [
	'user' => 'view',
	'admin' => 'edit',
];
$hierarchy = [
	'user' => [],
	'admin' => ['user'],
];

$rbac = new Rbac();

foreach ($roles as $role) {
	$rbacRole = new Role($role);
	$rbacRole->addPermission($permissions[$role]);

	foreach ($hierarchy[$role] as $parent) {
		$rbacRole->addParent(new Role($parent));
	}

	$rbac->addRole($rbacRole);
}


$user = $rbac->getRole('user');
var_dump($rbac->isGranted($user, 'view'));
var_dump($rbac->isGranted($user, 'edit'));

$admin = $rbac->getRole('admin');
var_dump($rbac->isGranted($admin, 'view'));
var_dump($rbac->isGranted($admin, 'edit'));

I expect admin to inherit all user permissions, but that it is not. It is because of new Role($parent)?
If so, how can I solve the problem?

This is normal PHP! Nothing strange here: two different objects.

Please look at the documentation:

Any parent role will inherit the permissions of their children.

https://docs.laminas.dev/laminas-permissions-rbac/intro/#permissions

Compare also with laminas-permissions-acl and the handling of the roles, maybe that’s what you’re looking for.

Thank you, my mistake. addChild must be used instead of addParent. Also we must remember to save role, and add it as child later. Final code:

$roles = ['user', 'admin'];
$permissions = [
	'user' => 'view',
	'admin' => 'edit',
];
$hierarchy = [
	'user' => [],
	'admin' => ['user'],
];

$rbacRoles = [];
$rbac = new Rbac();

foreach ($roles as $role) {
	$rbacRoles[$role] = new Role($role);
	$rbacRoles[$role]->addPermission($permissions[$role]);

	foreach ($hierarchy[$role] as $child) {
		echo 'add child |' . $child . '| to role |' . $rbacRoles[$role]->getName() . '|' . PHP_EOL;
		$rbacRoles[$role]->addChild($rbacRoles[$child]);
	}

	$rbac->addRole($rbacRoles[$role]);
}

foreach ($rbac->getRoles() as $role) {
	echo 'role |' . $role->getName() . '| try to |view| - ' . ($rbac->isGranted($role->getName(), 'view') ? 'granted' : 'denied') . PHP_EOL;
	echo 'role |' . $role->getName() . '| try to |edit| - ' . ($rbac->isGranted($role->getName(), 'edit') ? 'granted' : 'denied') . PHP_EOL;
}

Work as expected:

add child |user| to role |admin|
role |user| try to |view| - granted
role |user| try to |edit| - denied
role |admin| try to |view| - granted
role |admin| try to |edit| - granted