Within PHP code, I just inject the the RoleHierarchyInterface and use this simple expression:
if (in_array($role, $this->roleHierarchy->getReachableRoleNames($user->getRoles()))) {
// whatever
}
In Twig, I wrote this simple extension (works with current Versions: Symfony 5.2 and Twig 3.3):
<?php
// /src/Twig/AccessCheckExtension.php
declare(strict_types=1);
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
class AccessCheckExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('has_role', [AccessCheckRuntime::class, 'hasRole'])
];
}
public function getFunctions(): array
{
return [
new TwigFunction('has_role', [AccessCheckRuntime::class, 'hasRole'])
];
}
}
and
<?php
// /src/Twig/AccessCheckRuntime.php
declare(strict_types=1);
namespace App\Twig;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Twig\Extension\RuntimeExtensionInterface;
class AccessCheckRuntime implements RuntimeExtensionInterface
{
/**
* this uses PHP 8.0 constructor property promotion to reduce the needed lines
**/
public function __construct(
protected RoleHierarchyInterface $roleHierarchy
){}
public function hasRole(UserInterface $user, string $role): bool
{
return in_array($role, $this->roleHierarchy->getReachableRoleNames($user->getRoles()));
}
}
This can be used in a Twig template as following:
{% if user|has_role('ROLE_WHATEVER') %}
Hello {{ user.name }}
{% endif %}
or
{% if has_role(user, 'ROLE_WHATEVER') %}
Hello {{ user.name }}
{% endif %}
Pretty straightforward. I prefer the filter variant.