Sf2/3 为不同的角色(用户)显示不同的表单

Sf2/3 Displaing different forms for Different roles(users)

我有一个需要复杂访问控制的应用程序。 Voters 是我需要在控制器级别做出决定的东西。 但是,我需要通过不同的方式为不同的用户构建表单。 示例:有 Admin(ROLE_ADMIN) 和 User(ROLE_USER)。有一个 Post 包含字段:

管理员必须能够编辑任何 Post 的所有字段。 用户 - 仅限特定字段:已发布、正文。 (顺便说一下,只有当他是这个 post 的作者时,但这是由投票者决定的)。

我找到的可能解决方案是 dynamic form modification。但是如果我们需要更复杂一些,比如posts属于Blog,Blog属于author。并且 Post 可以由博客的直接作者和作者编辑。 并且博客的作者也可以编辑 postedAt 字段,但是 post.

的直接作者不能这样做

我需要在 PRE_BIND 侦听器中编写一些登录信息。

也许对于这种情况有某种常见的做法,或者有人可以展示他们自己的例子。

动态表单修改似乎没有必要。用户登录后,角色不应更改。

您可以在您的表单类型中注入 security.authorization_checker 服务,并在 buildForm 方法中使用它来有条件地将字段添加到您的表单中。根据表格的不同程度,如果 if 语句过多,这可能会变得混乱。在那种情况下,我建议完全编写不同的表单类型(可能为重复的事情扩展基本表单类型)。

您可以创建 form type extension

想象一个表单类型,您希望仅在授予 ROLE_ADMIN 时才显示字段。为此,您只需在字段中添加一个新的 属性(本例中为 'author')

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('published', 'text')
        ->add('moderated', 'text')
        ->add('author', 'text', [
            'is_granted' => 'ROLE_ADMIN',
        ])
    ;
}

要解释此参数,您必须通过注入 SecurityContext Symfony 来创建表单类型扩展,以确保登录用户的权限。

<?php

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContextInterface;

class SecurityTypeExtension extends AbstractTypeExtension
{
    /**
     * The security context
     * @var SecurityContextInterface
     */
    private $securityContext;

    /**
     * Object constructor
     */
    public function __construct(SecurityContextInterface $securityContext)
    {
        $this->securityContext = $securityContext;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $grant = $options['is_granted'];
        if (null === $grant || $this->securityContext->isGranted($grant)) {
            return;
        }

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $form = $event->getForm();
            if ($form->isRoot()) {
                return;
            }

            $form->getParent()->remove($form->getName());
        });
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefined(array('is_granted' => null));
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'form';
    }

}

最后,您只需将扩展程序另存为服务即可:

services:
    yourbundle.security_type_extension:
        class: YourProject\Bundle\ForumBundle\Form\Extension\SecurityTypeExtension
        arguments:
            - @security.context
        tags:
            - { name: form.type_extension, alias: form }