E
E
Evgeny Komarov2018-10-17 16:02:54
symfony
Evgeny Komarov, 2018-10-17 16:02:54

Symfony form how to save collections?

Good day. I'm just learning symbols and ran into a problem that I don't know how to solve. There is a user (name, login, password). I'm adding users via symfony form and it works great, the data is stored in the database.
If I add roles for the user that should be in the form of a multiselect on the interface, I get an error when saving:

Could not determine access type for property "roles" in class "App\Entity\User": Neither the property "roles" nor one of the methods "addRol()"/"removeRol()", "addRole()"/" removeRole()", "setRoles()", "roles()", "__set()" or "__call()" exist and have public access in class "App\Entity\User"..

the code is shortened, only the essence
#App\Entity\User;
class User implements UserInterface, \Serializable
{

    // различные пользовательские поля

    /**
     * @var ArrayCollection|null
     *
     * @ORM\ManyToMany(targetEntity="App\Entity\Role", cascade={"persist"})
     * @ORM\JoinTable(name="users_roles",
     *     joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="roles_id", referencedColumnName="id")}
     * )
     */
    private $roles;

    public function __construct()
    {
        $this->roles = new ArrayCollection();
    }

    /**
     * @return array
     */
    public function getRoles(): array
    {
        $roles = [];
        /**
         * @var int  $index
         * @var Role $role
         */
        foreach ($this->roles->toArray() as $index => $role) {
            $roles[$index] = $role->getName();
        }

        return $roles;
    }

    /**
     * @param Role $role
     *
     * @return User
     */
    public function addRole(Role $role): User
    {
        if (!$this->roles->contains($role)) {
            $this->roles->add($role);
        }

        return $this;
    }
}

#App\Entity\Role;

class Role
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @return int|null
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    /**
     * @param string $name
     *
     * @return Role
     */
    public function setName(string $name): Role
    {
        $this->name = $name;

        return $this;
    }
}

# App\Form\UserType;
class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            /* различные пользовательские поля */
            ->add(
                'roles',
                EntityType::class,
                [
                    'class' => Role::class,
                    'choice_label' => 'name',
                    'label' => 'Роли пользователя',
                    'multiple' => true,
                ]
            )
        ;
    }

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

public function addUser(Request $request): Response
    {
        $user = new User();

        $form = $this->createForm(UserType::class, $user);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();

            return $this->redirect($this->generateUrl('users'));
        }

        return $this->redirect($this->generateUrl('users'));
    }

Poke your nose, what to look at?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vadim, 2018-10-17
@maNULL

Your User class implements UserInterface. The UserInterface is:

/**
     * Returns the roles granted to the user.
     *
     *     public function getRoles()
     *     {
     *         return array('ROLE_USER');
     *     }
     *
     * Alternatively, the roles might be stored on a ``roles`` property,
     * and populated in any number of different ways when the user object
     * is created.
     *
     * @return (Role|string)[] The user roles
     */
    public function getRoles();

And above: I.e. getRoles should return an array of strings or Symfony\Component\Security\Core\Role\Role. Perhaps you should create your own roles, separate from the symphony ones? of type getRolesApp().

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question