3

ユーザーに割り当てられた役割を管理したいユーザー編集フォームがあります。

現在、複数選択リストがありますが、security.ymlで定義されているロール階層をリストに追加する方法がありません。

この情報をFormTypeクラスのフォームビルダーに取得する方法はありますか?

$builder->add('roles', 'choice', array(
                'required' => true,
                'multiple' => true,
                'choices' => array(),
            ));

周りを見回すと、コントローラーのコンテナーから次の機能を使用してロールを取得できることがわかりました。

$roles = $this->container->getParameter('security.role_hierarchy.roles');

また、これをservices.xmlのFormTypeクラスに挿入される依存関係として設定できる可能性があることも発見しました。

<parameters>
    <parameter key="security.role_heirarchy.roles">ROLE_GUEST</parameter>
</parameters>
<services>
    <service id="base.user.form.type.user_form" class="Base\UserBundle\Form\UserType" public="false">
        <tag name="form.type" />
        <call method="setRoles">
            <argument>%security.role_heirarchy.roles%</argument>
        </call>
    </service>
</services>

ただし、これは機能せず、setRolesメソッドを呼び出さないようです。

では、どうすればこれを機能させることができますか?

4

4 に答える 4

9

あなたのコントローラーで

$editForm = $this->createForm(new UserType(), $entity, array('roles' => $this->container->getParameter('security.role_hierarchy.roles')));

UserTypeの場合:

$builder->add('roles', 'choice', array(
    'required' => true,
    'multiple' => true,
    'choices' => $this->refactorRoles($options['roles'])
))

[...]

public function getDefaultOptions()
{
    return array(
        'roles' => null
    );
}

private function refactorRoles($originRoles)
{
    $roles = array();
    $rolesAdded = array();

    // Add herited roles
    foreach ($originRoles as $roleParent => $rolesHerit) {
        $tmpRoles = array_values($rolesHerit);
        $rolesAdded = array_merge($rolesAdded, $tmpRoles);
        $roles[$roleParent] = array_combine($tmpRoles, $tmpRoles);
    }
    // Add missing superparent roles
    $rolesParent = array_keys($originRoles);
    foreach ($rolesParent as $roleParent) {
        if (!in_array($roleParent, $rolesAdded)) {
            $roles['-----'][$roleParent] = $roleParent;
        }
    }

    return $roles;
}
于 2012-05-09T16:12:48.320 に答える
2

独自のタイプを作成してからサービスコンテナを渡すことができ、そこからロール階層を取得できます。

まず、独自のタイプを作成します。

class PermissionType extends AbstractType 
{
    private $roles;

    public function __construct(ContainerInterface $container)
    {
        $this->roles = $container->getParameter('security.role_hierarchy.roles');
    }
    public function getDefaultOptions(array $options)
    {
        return array(
              'choices' => $this->roles,
        );
    );

    public function getParent(array $options)
    {
        return 'choice';
    }

    public function getName()
    {
        return 'permission_choice';
    }
}

次に、タイプをサービスとして登録し、パラメーターを設定する必要があります。

services:
      form.type.permission:
          class: MyNamespace\MyBundle\Form\Type\PermissionType
          arguments:
            - "@service_container"
          tags:
            - { name: form.type, alias: permission_choice }

次に、フォームの作成中に、*permit_choice*フィールドを追加するだけです。

public function buildForm(FormBuilder $builder, array $options)
{
    $builder->add('roles', 'permission_choice');
}

階層のないロールのリストを1つだけ取得したい場合は、何らかの方法で階層をフラットにする必要があります。考えられる解決策の1つは、次のとおりです。

class PermissionType extends AbstractType 
{
    private $roles;

    public function __construct(ContainerInterface $container)
    {
        $roles = $container->getParameter('security.role_hierarchy.roles');
        $this->roles = $this->flatArray($roles);
    }

    private function flatArray(array $data)
    {
        $result = array();
        foreach ($data as $key => $value) {
            if (substr($key, 0, 4) === 'ROLE') {
                $result[$key] = $key;
            }
            if (is_array($value)) {
                $tmpresult = $this->flatArray($value);
                if (count($tmpresult) > 0) {
                    $result = array_merge($result, $tmpresult);
                }
            } else {
                $result[$value] = $value;
            }
        }
        return array_unique($result);
    }
    ...
}
于 2012-06-18T15:07:09.293 に答える
2

webda2lが提供する$options配列を使用したソリューションは、Symfony2.3では機能しません。それは私にエラーを与えます:

オプション「roles」は存在しません。

フォーム型コンストラクターにパラメーターを渡すことができることがわかりました。

コントローラ内:

$roles_choices = array();

$roles = $this->container->getParameter('security.role_hierarchy.roles');

# set roles array, displaying inherited roles between parentheses
foreach ($roles as $role => $inherited_roles)
{
    foreach ($inherited_roles as $id => $inherited_role)
    {
        if (! array_key_exists($inherited_role, $roles_choices))
        {
            $roles_choices[$inherited_role] = $inherited_role;
        }
    }

    if (! array_key_exists($role, $roles_choices))
    {
        $roles_choices[$role] = $role.' ('.
            implode(', ', $inherited_roles).')';
    }
}

# todo: set $role as the current role of the user

$form = $this->createForm(
    new UserType(array(
        # pass $roles to the constructor
        'roles' => $roles_choices,
        'role' => $role
    )), $user);

UserType.phpの場合:

class UserType extends AbstractType
{
    private $roles;
    private $role;

    public function __construct($options = array())
    {
        # store roles
        $this->roles = $options['roles'];
        $this->role = $options['role'];
    }
    public function buildForm(FormBuilderInterface $builder,
        array $options)
    {
        // ...
        # use roles
        $builder->add('roles', 'choice', array(
            'choices' => $this->roles,
            'data' => $this->role,
        ));
        // ...
    }
}

彼のおかげで、私はマルチェロ・ヴォックからアイデアを取り入れました!

于 2013-06-25T12:36:48.437 に答える
1

symfony 2.3へ:

<?php

namespace Labone\Bundle\UserBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class PermissionType extends AbstractType 
{
    private $roles;

    public function __construct(Container $container)
    {
        $roles = $container->getParameter('security.role_hierarchy.roles');
        $this->roles = $this->flatArray($roles);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'choices' => $this->roles
        ));
    }

    public function getParent()
    {
        return 'choice';
    }

    public function getName()
    {
        return 'permission_choice';
    }

    private function flatArray(array $data)
    {
        $result = array();
        foreach ($data as $key => $value) {
            if (substr($key, 0, 4) === 'ROLE') {
                $result[$key] = $key;
            }
            if (is_array($value)) {
                $tmpresult = $this->flatArray($value);
                if (count($tmpresult) > 0) {
                    $result = array_merge($result, $tmpresult);
                }
            } else {
                $result[$value] = $value;
            }
        }
        return array_unique($result);
    }
}
于 2013-09-27T14:14:48.207 に答える