Symfony 7.2.*表单调用User实体无法读取user_email属性求助
开发Symfony 7.2.x版本表单时,调用User实体出现错误:无法读取类App\Entity\User中的user_email属性,但该属性确实存在于实体中。以下是相关代码,请求解决该问题。
User实体代码
<?php namespace App\Entity; use App\Repository\UserRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; #[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\Table(name: '`user`')] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['user_email'])] class User implements UserInterface, PasswordAuthenticatedUserInterface { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $user_id = null; #[ORM\Column(length: 180)] private ?string $user_email = null; /** * @var list<string> The user roles */ #[ORM\Column] private array $user_roles = []; /** * @var ?string The hashed password */ #[ORM\Column] private ?string $user_password = null; #[ORM\Column(length: 50, nullable: true)] private ?string $user_firstname = null; #[ORM\Column(length: 50, nullable: true)] private ?string $user_surname = null; #[ORM\Column(length: 15, nullable: true)] private ?string $user_phone = null; #[ORM\Column(length: 200, nullable: true)] private ?string $user_address = null; #[ORM\Column(type: Types::DATE_MUTABLE, nullable: true)] private ?\DateTime $user_birthdate = null; #[ORM\Column(type: Types::BLOB, nullable: true)] private $user_photo = null; #[ORM\Column(length: 50)] private ?string $user_pseudo = null; public function getId(): ?int { return $this->user_id; } public function getEmail(): ?string { return $this->user_email; } public function setEmail(string $user_email): static { $this->user_email = $user_email; return $this; } /** * A visual identifier that represents this user. * * @see UserInterface */ public function getUserIdentifier(): string { return (string) $this->user_email; } /** * @see UserInterface */ public function getRoles(): array { $user_roles = $this->user_roles; // guarantee every user at least has ROLE_USER $user_roles[] = 'ROLE_USER'; return array_unique($user_roles); } /** * @param list<string> $user_roles */ public function setRoles(array $user_roles): static { $this->user_roles = $user_roles; return $this; } /** * @see PasswordAuthenticatedUserInterface */ public function getPassword(): ?string { return $this->user_password; } public function setPassword(string $user_password): static { $this->user_password = $user_password; return $this; } /** * @see UserInterface */ public function eraseCredentials(): void { // If you store any temporary, sensitive data on the user, clear it here // $this->plainPassword = null; } public function getUserFirstname(): ?string { return $this->user_firstname; } public function setUserFirstname(?string $user_firstname): static { $this->user_firstname = $user_firstname; return $this; } public function getUserSurname(): ?string { return $this->user_surname; } public function setUserSurname(?string $user_surname): static { $this->user_surname = $user_surname; return $this; } public function getUserPhone(): ?string { return $this->user_phone; } public function setUserPhone(?string $user_phone): static { $this->user_phone = $user_phone; return $this; } public function getUserAddress(): ?string { return $this->user_address; } public function setUserAddress(?string $user_address): static { $this->user_address = $user_address; return $this; } public function getUserBirthdate(): ?\DateTime { return $this->user_birthdate; } public function setUserBirthdate(?\DateTime $user_birthdate): static { $this->user_birthdate = $user_birthdate; return $this; } public function getUserPhoto() { return $this->user_photo; } public function setUserPhoto($user_photo): static { $this->user_photo = $user_photo; return $this; } public function getUserPseudo(): ?string { return $this->user_pseudo; } public function setUserPseudo(string $user_pseudo): static { $this->user_pseudo = $user_pseudo; return $this; } }
RegisterUserTypeForm表单代码
<?php namespace App\Form; use App\Entity\User; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class RegisterUserTypeForm extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('user_email', EmailType::class, [ 'label' => 'Saisir une adresse mail valide', 'attr' => [ 'placeholder' => 'Adresse@mail.com' ] ]) ->add('user_pseudo', TextType::class, [ 'label' => 'Saisir un nom d\'utilisateur', 'attr' => [ 'placeholder' => 'Pseudo-123' ] ]) ->add('user_password', PasswordType::class, [ 'label' => 'Saisir un mot de passe', 'attr' => [ 'placeholder' => '************' ] ]) ->add('submit', SubmitType::class, [ 'label' => 'Valider', 'attr' => [ 'class' => 'button' ] ]); } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => User::class, ]); } }
RegisterController控制器代码
<?php namespace App\Controller; use App\Entity\User; use App\Form\RegisterUserTypeForm; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; final class RegisterController extends AbstractController { #[Route('/Inscription', name: 'app_register')] public function index(Request $request, EntityManagerInterface $entityManager): Response { $user = new User(); $form = $this->createForm(RegisterUserTypeForm::class, $user); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $entityManager->persist($user); $entityManager->flush(); } return $this->render('register/index.html.twig', [ 'registerForm' => $form->createView(), ]); } }
问题原因与解决方法
问题根源
Symfony表单默认通过字段名匹配对应的getter/setter方法:表单中使用user_email字段,会自动尝试调用getUserEmail()和setUserEmail()方法,但你的User实体中,该属性对应的方法是getEmail()和setEmail(),导致属性读取失败。同理,user_password字段也存在相同问题,实体中是getPassword()而非getUserPassword()。
解决方式一(推荐):修改表单字段的属性映射
在表单的字段配置中,添加property_path参数,指定实体中对应的方法名(去掉前缀get/set后的驼峰名):
$builder ->add('user_email', EmailType::class, [ 'label' => 'Saisir une adresse mail valide', 'attr' => [ 'placeholder' => 'Adresse@mail.com' ], 'property_path' => 'email' // 指定对应getEmail()/setEmail() ]) ->add('user_pseudo', TextType::class, [ 'label' => 'Saisir un nom d\'utilisateur', 'attr' => [ 'placeholder' => 'Pseudo-123' ] ]) ->add('user_password', PasswordType::class, [ 'label' => 'Saisir un mot de passe', 'attr' => [ 'placeholder' => '************' ], 'property_path' => 'password' // 指定对应getPassword()/setPassword() ]) // ... 其他字段
这种方式不需要修改实体方法,避免影响Symfony Security组件的默认约定(getEmail()、getPassword()是Security组件要求的标准方法)。
解决方式二:修改实体的getter/setter方法名
将实体中的getEmail()改为getUserEmail(),setEmail()改为setUserEmail();getPassword()改为getUserPassword(),setPassword()改为setUserPassword(),保持和表单字段名一致:
// 修改后的Email方法 public function getUserEmail(): ?string { return $this->user_email; } public function setUserEmail(string $user_email): static { $this->user_email = $user_email; return $this; } // 修改后的Password方法 public function getUserPassword(): ?string { return $this->user_password; } public function setUserPassword(string $user_password): static { $this->user_password = $user_password; return $this; }
注意:此方式需要同时保留getEmail()和getPassword()方法(或者修改getUserIdentifier()和Security相关逻辑),否则会导致Symfony Security组件无法正常工作。
内容的提问来源于stack exchange,提问作者NoGrand6724

