How to customize form field based on user roles in Symfony2/3?

sentenza picture sentenza · Feb 16, 2016 · Viewed 9.3k times · Source

Is there a correct way to customize a form depending on the role of the user that requests it?

My scenario is pretty simple: I need to hide some fields if the user has not the ROLE_ADMIN granted. I tried to avoid the field display on Twig, but

  {% if is_granted('ROLE_ADMIN') %}
              {{form_row(form.field)}}
  {% endif %}

not works, because the form builder bypass this check.

Symfony version: 2.8.2

EDIT

Thanks to the @Rooneyl suggestion I've found the solution:

At first, you need to add the 'role' key to the options parameter. So, in the configureOptions() $options['role'] is always ROLE_USER.

/**
 * @param OptionsResolver $resolver
 */
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'MyBundle\Entity\Ticket',
        'role' => 'ROLE_USER'
    ));
}

Then in the controller you have to pass the getRoles() array:

$user_roles = $this->getUser()->getRoles();
$form = $this->createForm('MyBundle\Form\TicketType', $ticket, array('role' => $user_roles));

Answer

Bart Bartoman picture Bart Bartoman · Feb 16, 2016

You can do it in your form.

Make a service for your form

app.form.type.task:
    class: AppBundle\Form\FormType
    arguments: ["@security.authorization_checker"]
    tags:
        - { name: form.type }

In your FormType, add a constructor to get your service.

private $authorization;
public function __construct(AuthorizationChecker $authorizationChecker)
{
    $this->authorization = $authorizationChecker;
}

Then, in your builder, you will be able to check user permission

$builder->add('foo');
if($this->authorization->isGranted('ROLE_ADMIN'))
{
   $builder->add('bar');
}

And then, finally, you can render your form

{% if form.formbar is defined %}
    {{ form_row(form.formbar ) }}
{% endif %}

Please note that it mean that your field may be null. Because maybe you want to see some of them visible by some users and others not.

Else, you can set a default value in your entity construct method, to make sure value won't be null if user don't/can't fill it.