To replay it a bit, here is my extended version of Romain Bruckert and Sash, which gives you such an array:
array:4 [βΌ "ROLE_USER" => "User" "ROLE_ALLOWED_TO_SWITCH" => "Allowed To Switch" "ROLE_ADMIN" => "Admin (User, Allowed To Switch)" "ROLE_SUPER_ADMIN" => "Super Admin (Admin (User, Allowed To Switch))" ]

This will help you find all roles that include a specific role : 
I know a lot of code, it can be done much better, but maybe it helps someone, or you can at least use snippets of this code.
protected static function flattenRoles($rolesHierarchy, $niceName = false, $withChildren = false, $withGrandChildren = false) { $flatRoles = []; foreach ($rolesHierarchy as $key => $roles) { if(!empty($roles)) { foreach($roles as $role) { if(!isset($flatRoles[$role])) { $flatRoles[$role] = $niceName ? self::niceRoleName($role) : $role; } } } $flatRoles[$key] = $niceName ? self::niceRoleName($key) : $key; if ($withChildren && !empty($roles)) { if (!$recursive) { if ($niceName) { array_walk($roles, function(&$item) { $item = self::niceRoleName($item);}); } $flatRoles[$key] .= ' (' . join(', ', $roles) . ')'; } else { $childRoles = []; foreach($roles as $role) { $childRoles[$role] = $niceName ? self::niceRoleName($role) : $role; if (!empty($rolesHierarchy[$role])) { if ($niceName) { array_walk($rolesHierarchy[$role], function(&$item) { $item = self::niceRoleName($item);}); } $childRoles[$role] .= ' (' . join(', ', $rolesHierarchy[$role]) . ')'; } } $flatRoles[$key] .= ' (' . join(', ', $childRoles) . ')'; } } } return $flatRoles; } protected static function niceRoleName($role) { return ucwords(strtolower(preg_replace(['/\AROLE_/', '/_/'], ['', ' '], $role))); }
source share