Symfony - Форма ChoiceType - Ошибка преобразования массива в строку - PullRequest
1 голос
/ 08 марта 2020

Я пытаюсь создать форму с вводом типа выбора для ролей полей моего пользователя сущности. Тем не менее, Symfony ответьте мне на ошибку «Ошибка преобразования массива в строку»

Мои роли не должны быть массивом, потому что они не являются множественными (иерархия ролей в security.yaml).

Вот мой Form Builder:

 $builder
        ->add('email')
        ->add('prenom')
        ->add('nom')
        ->add('password', PasswordType::Class)
        ->add('confirm_password', PasswordType::Class)
        ->add('roles', ChoiceType::class, [
            'choices'  => [
                'Utilisateur' => "ROLE_USER",
                'Valideur' => "ROLE_VALIDEUR",
                'Administrateur' => "ROLE_ADMIN",                    
            ],

        ])

И мой пользовательский объект:

class User implements UserInterface
{
/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\Length(min="8", minMessage="Votre mot de passe doit contenir au moins 8 carractères")
 */
private $password;

/**
 * @Assert\EqualTo(propertyPath="password", message="Vous n'avez pas tapé le même mot de passe")
 */
private $confirm_password;

/**
 * @ORM\Column(type="simple_array")
 */
private $roles = array();

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\NotBlank
 */
private $prenom;

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\NotBlank
 */
private $nom;

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\Email()
 * @Assert\NotBlank
 */
private $email;



public function getId(): ?int
{
    return $this->id;
}

public function getPassword(): ?string
{
    return $this->password;
}

public function setPassword(string $password): self
{
    $this->password = $password;

    return $this;
}

public function getConfirmPassword(): ?string
{
    return $this->confirm_password;
}

public function setConfirmPassword(string $confirm_password): self
{
    $this->confirm_password = $confirm_password;

    return $this;
}

public function getRoles(): array
{
    return array_unique($this->roles);
}

public function setRoles(array $roles): self
{
    $this->roles = $roles;

    return $this;
}

public function getPrenom(): ?string
{
    return $this->prenom;
}

public function setPrenom(?string $prenom): self
{
    $this->prenom = $prenom;

    return $this;
}

public function getNom(): ?string
{
    return $this->nom;
}

public function setNom(?string $nom): self
{
    $this->nom = $nom;

    return $this;
}

public function getEmail(): ?string
{
    return $this->email;
}

public function setEmail(string $email): self
{
    $this->email = $email;

    return $this;
} 

public function getUsername(): ?string
{
    return $this->email;
}

public function eraseCredentials()
{
}

public function getSalt()
{
}
}

Не могли бы вы объяснить мне, где проблемы в моем пользовательском объекте (или где-то еще), пожалуйста?

Ответы [ 2 ]

0 голосов
/ 21 марта 2020

Я пробовал что-то другое, чтобы решить проблему, но все еще не вполне нормально.

Чтобы избежать преобразования массива в строку, я изменил свою сущность User следующим образом:

/**
 * @ORM\Column(type="string", length=100)
 */
private $roles;

public function getRoles(): array
{
    return array($this->roles);
}

public function setRoles(?string $roles): self
{
    $this->roles = $roles;

    return $this;
}

Роли строковые, но мне нужно преобразовать его в массив в методе getRoles, потому что он нужен UserAuthenticationProvider.

В моем контроллере нет ничего особенного, только создание формы с помощью сущности.

/**
 * @Route("/users/nouveau", name="users_nouveau")
 */
public function nouveau()
{ 
    $newUser = new User();
    $form = $this->createForm(UserType::class, $newUser);

    return $this->json([], 200);
}

Вот моя форма UserType:

class UserType extends AbstractType
{

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('email')
        ->add('prenom')
        ->add('nom')
        ->add('password', PasswordType::Class)
        ->add('confirm_password', PasswordType::Class)
        ->add('roles', ChoiceType::class, [
            'choices'  => [
                'Utilisateur' => "ROLE_USER",
                'Valideur' => "ROLE_VALIDEUR",
                'Administrateur' => "ROLE_ADMIN",                    
            ],

        ])
    ;
}

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

}

Я не понимаю, почему все еще существует ошибка преобразования массива в строку.

0 голосов
/ 08 марта 2020

Проблема здесь в том, что Symfony пытается преобразовать значение типа выбора в массив для пользовательских ролей, поскольку значение выбора представляет собой строку 'Utilisateur' => "ROLE_USER".

Единственное решение состоит в том, чтобы не определять специфицированный c объект для формы и после применения значений к пользовательскому объекту.

  1. Сначала создайте тип пользователя, когда форма будет иметь вид:
class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // The builder doesn't change
        $builder
            ->add('email')
            ->add('prenom')
            ->add('nom')
            ->add('password', PasswordType::Class)
            ->add('confirm_password', PasswordType::Class)
            ->add('roles', ChoiceType::class, [
                'choices' => [
                    'Utilisateur' => 'ROLE_USER',
                    'Validateur' => 'ROLE_VALIDATEUR',
                    'Administrateur' => 'ROLE_ADMIN'
                ]
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([]);
    }
}
После этого создайте свой контроллер и создайте форму:
class UserController extends AbstractController
{
    public function index(Request $request, EntityManagerInterface $manager)
    {
        // Create the form
        $form = $this->createForm(UserType::class);

        // Render the Twig file and pass the form as a view
        return $this->render('user/index.html.twig', ['form' => $form->createView()]);
    }
}
Затем вам нужно обработать форму и присвоить все свойства вашей сущности следующим образом:
public function index(Request $request, EntityManagerInterface $manager)
{
    $form = $this->createForm(UserType::class);

    // Processing the form from the request
    $form->handleRequest($request);

    // Check if form is submitted
    if($form->isSubmitted()) {

        // Fetch data from the form
        $data = $form->getData();

        // Create user from data
        $user = (new User)
            ->setEmail($data['email'])
            ->setPrenom($data['prenom'])
            ->setNom($data['nom'])
            ->setPassword($data['password'])
            ->setConfirmPassword($data['confirm_password'])
            // Here, we convert the string to an array
            ->setRoles([$data['roles']]);

        // Add the user to the database
        $manager->persist($user);
        $manager->flush();
    }

    return $this->render('user/index.html.twig', ['form' => $form->createView()]);
}
Есть еще одна проблема с кодом выше: нарушения не запускаются, и возникает ошибка при возникновении конфликтов между двумя объектами (во время $manager->flush()). Следующий код является исправлением (мы можем использовать валидатор , чтобы проверить, является ли сущность действительной):
// Request validator as injection dependency
public function index(Request $request, EntityManagerInterface $manager, ValidatorInterface $validator)
{
    $form = $this->createForm(UserType::class);

    // Set default values for validation variables
    $violations = null;
    $conflict = false;

    $form->handleRequest($request);
    if($form->isSubmitted()) {
        $data = $form->getData();

        $user = (new User)
            ->setEmail($data['email'])
            ->setPrenom($data['prenom'])
            ->setNom($data['nom'])
            ->setPassword($data['password'])
            ->setConfirmPassword($data['confirm_password'])
            // Here, we convert the string to an array
            ->setRoles([$data['roles']]);

        // Get violations from the user entity with the 'validate' function
        $violations = $validator->validate($user);

        // Check if there are no violations. If it is, the user is valid
        if($violations->count() === 0) {
            $manager->persist($user);

            // Catch a unique constraint violation exception during flushing
            try {
                $manager->flush();
            } catch(UniqueConstraintViolationException $e) {
                $conflict = true;
            }
        }
    }

    return $this->render('user/index.html.twig', [
        'form' => $form->createView(),

        // Pass violations and conflict
        'violations' => $violations,
        'conflict' => $conflict
    ]);
}

Я надеюсь, что помогу вам!

Если вы хотите создать поле, в котором мы можем выбрать несколько ролей, эта ссылка может помочь вам (веб-сайт на французском языке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...