How to create a form to edit user roles with FriendsOfSymfony UserBundle
Asked Answered
E

2

5

I'm trying to create a controller where I can edit the roles of a user (just that, nothing else) and I'm king of stuck.

I've created a form type:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'roles', 'choice', [
                'choices' => ['ROLE_ADMIN', 'ROLE_USER', 'ROLE_CUSTOMER'],
                'expanded' => true,
                'multiple' => true,
            ]
        )
        ->add('send', 'submit');
}

First, what would be the best way to retrieve the roles? Is there any way to associate a label to them?

In the controller I have this:

/**
     * User role edition
     *
     * @Route(
     *      path="/edit-roles",
     *      name = "backoffice_user_edit_roles",
     *      requirements = {
     *          "id_user" = "\d*",
     *      },
     *      methods = {"GET"}
     * )
     *
     * @Security("has_role('ROLE_ADMIN')")
     *
     * @Template
     */
    public function editRolesAction($id_user)
    {
        $user = $this->user_repository->findOneById($id_user);
        $form = $this->form_factory->create('dirital_user_roles_form_type', $user);
        return [
            'form' => $form->createView(),
            'user' => $user
        ];
    }

Problems that I have:

  • The form doesn't get populate with the current user roles, how should I do that?
  • When receiving the form, how can I update the user?

Thanks a lot

Equimolecular answered 4/11, 2015 at 14:25 Comment(3)
If your user has a comma delimited set of roles then you need to plugin a data transformer (symfony.com/doc/current/cookbook/form/data_transformers.html) to convert the roles to and from an array.Veator
@Veator its serialized so when you call getRoles returns an array, that shouldn't be a problem :)Equimolecular
Fair enough, your choices array needs to be keyed: symfony.com/doc/current/reference/forms/types/…Veator
E
9

Actually it was easier than I thought – this is the form:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'roles', 'choice', [
                'choices' => ['ROLE_ADMIN' => 'ROLE_ADMIN', 'ROLE_USER' => 'ROLE_USER', 'ROLE_CUSTOMER' => 'ROLE_CUSTOMER'],
                'expanded' => true,
                'multiple' => true,
            ]
        )
        ->add('save', 'submit', ['label' => 'ui.button.save']);
}

And the controller:

public function editRolesAction(Request $request, $id_user)
{
    $user = $this->user_repository->findOneById($id_user);
    $form = $this->form_factory->create('dirital_user_roles_form_type', $user);
    $form->handleRequest($request);
    if($form->isValid())
    {
        $this->addFlash('success', 'section.backoffice.users.edit_roles.confirmation');
        $this->em->persist($user);
        $this->em->flush();
        $this->redirectToRoute('backoffice_user_edit_roles', ['id_user' => $user->getId()]);
    }
    return [
        'form' => $form->createView(),
        'user' => $user
    ];
}

The only part that remains to do is grabbing the form choices from the config instead of hardcoding them.

Equimolecular answered 5/11, 2015 at 8:40 Comment(2)
On the form I'm getting this error: Notice: Array to string conversion reference question: #39199346 have any idea about whats happening?Olnay
add 'multiple' => true on your roles fieldTade
S
0

To rehuse easily in other controllers or actions, I like more this approach:

<?php

namespace App\Form;

use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\CallbackTransformer;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add(
                'roles', 'choice', [
                    'choices' => ['ROLE_ADMIN' => 'ROLE_ADMIN', 'ROLE_USER' => 'ROLE_USER', 'ROLE_CUSTOMER' => 'ROLE_CUSTOMER'],
                    'expanded' => true,
                    'multiple' => true,
                ]
            )
            ->add('save', 'submit', ['label' => 'ui.button.save']);
        ;

        // Data transformer
        $builder->get('roles')
            ->addModelTransformer(new CallbackTransformer(
                function ($rolesArray) {
                     // transform the array to a string
                     return count($rolesArray)? $rolesArray[0]: null;
                },
                function ($rolesString) {
                     // transform the string back to an array
                     return [$rolesString];
                }
        ));
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

without touching the controller. I added the whole file to see the clases you need to import

Sec answered 1/12, 2021 at 15:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.