user2182349
user2182349

Reputation: 9782

FOSUserBundle - Group assignment in UserType form

I am creating a web interface that allows users to be assigned into groups with https://github.com/FriendsOfSymfony/FOSUserBundle and version 2.7 of Symfony on CentOS 6.x.

This is the code I have:

use FOS\UserBundle\Model\GroupManager;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

/**
 * @Route("/admin/user")
 */
public function indexAction( Request $request )
{
    $this->denyAccessUnlessGranted( 'ROLE_ADMIN', null, 'Unable to access this page!' );

    $groups = $this->get('fos_user.group_manager')->findGroups();
    $groupNames = [];
    foreach ($groups as $g) {
        $groupNames[] = $g->getName();
    }

    $user = new User();
    $user_form = $this->createForm( new UserType(), $user );
    $user_form->add( 'groups', ChoiceType::class, [
        'choices' => $groupNames,
        'choices_as_values' => true,
        'multiple' => false
    ] );

    return $this->render( 'admin/user/index.html.twig', array(
                'user_form' => $user_form->createView(),
                'base_dir' => realpath( $this->container->getParameter( 'kernel.root_dir' ) . '/..' ),
            ) );
}

I've read the documentation at Symfony and Googled, but the debugger is throwing an error (Could not load type "Symfony\Component\Form\Extension\Core\Type\ChoiceType").

I have two questions:

  1. How can I add a choice field into the form that allows the user to select which groups to assign a user into?

  2. Would it be better to add the group selection element into the UserType?

This is what I have for UserType (from following the Symfony docs):

class UserType extends AbstractType
{

    public function buildForm( FormBuilderInterface $builder, array $options )
    {
        $builder
                ->add( 'username' )
                ->add( 'email' )
                ->add( 'enabled', 'checkbox' )
                ->add( 'locked', 'checkbox' )
                ->add( 'expired', 'checkbox' )
                ->add( 'credentialsExpired', 'checkbox' )
        ;
    }

Thank you to @hendrathings for offering a much better solution than I had.

I upgraded to Symfony 3.0 to avoid version issues in the future.

This is what I finally implemented:

In UserType.php

// Additional dependencies ...

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

class UserType extends AbstractType
{

    public function buildForm( FormBuilderInterface $builder, array $data )
    {
        $builder
                ->add( 'username', TextType::class )
                ->add( 'email', TextType::class )
                ->add( 'enabled', CheckboxType::class )
                ->add( 'locked', CheckboxType::class )
                ->add( 'groups', ChoiceType::class, [
                    'choices' => $data['group_names'],
                ] );
    }

    public function configureOptions( OptionsResolver $resolver )
    {
        $resolver->setDefaults( array(
            'data_class' => 'AppBundle\Entity\User',
            'group_names' => []
        ) );
    }

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

}

It is called from the controller like so:

    $groups = $this->get( 'fos_user.group_manager' )->findGroups();
    $groupNames = [];
    foreach( $groups as $g )
    {
        $groupNames[$g->getName()] = $g->getId();
    }
    $user = new User();
    $user_form = $this->createForm( UserType::class, $user, array( 'group_names' => $groupNames ));

This was also helpful: Pass custom options to a symfony2 form

I'm not entirely happy with my implementation, but I think I will leave it for now and move on.

Upvotes: 0

Views: 540

Answers (2)

user2182349
user2182349

Reputation: 9782

This is the solution I have working now.

Controller

public function indexAction( Request $request )
{
    $this->denyAccessUnlessGranted( 'ROLE_ADMIN', null, 'Unable to access this page!' );

    $user_form = $this->createForm( UserType::class, null, [] );

    return $this->render( 'admin/index.html.twig', array(
                'user_form' => $user_form->createView(),
                'base_dir' => realpath( $this->container->getParameter( 'kernel.root_dir' ) . '/..' ),
            ) );
}    

UserType / Form

public function buildForm( FormBuilderInterface $builder, array $options )
{

    $builder
            ->add( 'username', TextType::class )
            ->add( 'email', TextType::class )
            ->add( 'enabled', CheckboxType::class )
            ->add( 'locked', CheckboxType::class )
            ->add( 'groups', EntityType::class, [
                'class' => 'AppBundle:Group',
                'choice_label' => 'name',
                'multiple' => true,
                'choices_as_values' => true,
                'expanded' => true
            ] );
}

public function configureOptions( OptionsResolver $resolver )
{
    $resolver->setDefaults( array(
        'groups' => [],
        'data_class' => 'AppBundle\Entity\User'
    ) );
}

Upvotes: 0

hendrathings
hendrathings

Reputation: 3765

Your symfony version is 2.7 and you use symfony 3.0 syntax. Try upgrade your symfony by composer.

Or change this part ChoiceType::class to choice. and remove use Symfony\Component\Form\Extension\Core\Type\ChoiceType as well.

1.How can I add a choice field into the form that allows the user to select which groups to assign a user into:

  • Add new field group in User entity class
  • Add _construct in UserType that pass of your group list (array)
  • Add new field group in UserType form. and call $this->group to set choiceType
  • Modify controller in $this->createForm( new UserType(), $user ); to $this->createForm( new UserType($group), $user );

so your UserType would be:

private $group;

public function __construct($group)
{
    $this->group = $group;
}

public function buildForm( FormBuilderInterface $builder, array $options )
{
    $builder
            ->add( 'username' )
            ...
            ->add( 'group', 'choice', array(
                'choice' => $this->group
                ... // Your setting
            ))
    ;
}

Call your form in controller:

$this->createForm( new UserType($group), $user );
  1. Yes. Make your code clean and understand.

Upvotes: 1

Related Questions