Symfony form как сохранять коллекции?

Доброго времени суток. Только изучаю симвофни и столкнулся с проблемой, которую не знаю как решить. Есть пользователь (фио, логин, пароль). Делаю добавление пользователей через symfony form и это прекрасно работает, данные сохраняются в БД.
Если я добавляю для пользователя роли, которые на интерфейсе должны быть в виде мультиселекта - при сохранении получаю ошибку:

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"..


код сокращен, только сама суть
#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'));
    }

Ткните носом, на что смотреть?
  • Вопрос задан
  • 611 просмотров
Решения вопроса 2
kylt_lichnosti
@kylt_lichnosti
У вас класс User реализует UserInterface. В UserInterface такое:
/**
     * 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();


А выше:
use Symfony\Component\Security\Core\Role\Role;

Т.е. надо что бы getRoles возвращал массив строк или Symfony\Component\Security\Core\Role\Role.

Возможно вам стоит создать свои роли, отдельные от симфонийских? Типа getRolesApp().
Ответ написан
maNULL
@maNULL Автор вопроса
Все оказалось куда интереснее (надо было вчитываться в суть ошибки)....
Компонент форм для своей работы требует метод сеттера ЛИБО пару add/remove методов. Добавление removeRole() решило проблему.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы