英文:
Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader::getIdValue(): Argument #1 ($object) must be of type ?object, string given
问题
这个错误信息表明在 Symfony 6.3 应用程序中修改联系人时出现了问题,具体是在表单处理过程中。错误消息指出在 Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader::getIdValue()
方法中,参数 #1 的类型应该是 ?object
,但实际上传递了一个字符串。这个问题通常是由于表单字段的某些配置或数据传递不正确导致的。
要解决这个问题,你可以执行以下步骤:
-
检查你的表单字段配置,特别是那些与关联实体相关的字段。确保它们正确地与相关的实体类联系在一起。
-
检查在修改联系人时如何传递联系人对象。你可以在控制器中的编辑操作中检查一下,确保正确地获取并传递了联系人对象。
-
确保联系人对象的数据是有效的,没有任何意外的数据类型问题。你可以在编辑操作中打印联系人对象的内容来进行调试,确保它是一个有效的 Contact 对象。
-
如果有必要,可以查看你的
ContactType
表单类,确保其中的字段配置正确。特别关注那些可能导致类型不匹配问题的字段。 -
最后,检查你的实体类
Contact
,确保属性与数据库字段的映射正确,并且 getter 和 setter 方法的类型和返回类型也正确。
通过仔细检查这些方面,你应该能够找到并解决引发该错误的问题。如果问题仍然存在,可以提供更多关于具体配置和数据的信息,以便进一步帮助你解决问题。
英文:
I'm working on a form to manage contacts within a Symfony 6.3 application. Contact creation works well.
However, when I try to modify a contact, instead of the form that would normally show up, there is the following error message:
> Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader::getIdValue(): Argument #1 ($object) must be of type ?object, string given, called in D:\2. TDEKDO\vendor\symfony\form\ChoiceList\ArrayChoiceList.php on line 134
>
screenshot of the error message
And when I dump the contact variable before assigning it to the form, it comes up as being an object:
contact variable as an object
This is my ContactType form:
`<?php
namespace App\Form;
use App\Entity\Contact;
use App\Entity\Adherent;
use App\Entity\TypeVoie;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class ContactType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$typevoies = $options['typevoies'];
$adherents = $options['adherents'];
$builder
->add('politesse', ChoiceType::class, [
'label' => 'Politesse',
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => [
'Mr' => 'Mr',
'Mme' => 'Mme'
]
])
->add('nom', TextType::class, [
'label' => 'Nom',
'constraints' => new Length([
'min' => 2,
'max' => 30
]),
'required' => true,
'attr' => [
'placeholder' => "Merci de saisir le nom de contact"
]
])
->add('prenom', TextType::class, [
'label' => 'Prénom',
'constraints' => new Length([
'min' => 2,
'max' => 30
]),
'required' => true,
'attr' => [
'placeholder' => "Merci de saisir le prénom de contact"
]
])
->add('tel', TelType::class, [
'label' => 'Téléphone',
'attr' => [
'placeholder' => "Merci de saisir le numero de téléphone"
]
])
->add('mobile', TelType::class, [
'label' => 'Mobile',
'attr' => [
'placeholder' => "Merci de saisir le numero de mobile"
]
])
->add('mail', TextType::class, [
'label' => 'Mail',
'attr' => [
'placeholder' => "Merci de saisir le mail"
]
])
->add('fonction', TextType::class, [
'label' => 'Fonction',
'attr' => [
'placeholder' => "Merci de saisir la fonction"
]
])
->add('annule')
->add('numvoie', TextType::class, [
'label' => 'Numero',
'attr' => [
'placeholder' => "Voie"
]
])
->add('typevoie', EntityType::class, [
'label' => 'Type de voie',
'class' => TypeVoie::class,
'choices' => $typevoies,
'choice_label' => 'libelle',
'required' => true,
'attr' => [
'placeholder' => "Merci de choisir le type de voie"
]
])
->add('adresse1')
->add('adresse2')
->add('adresse3')
->add('postal')
->add('ville')
->add('adherent', EntityType::class, [
'label' => 'Adhérent',
'class' => Adherent::class,
'choices' => $adherents,
'choice_label' => 'nom'
])
->add('submit', SubmitType::class, [
'label' => 'Inserer',
'attr' => [
'class' => 'btn btn-success w-100'
]
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Contact::class,
'typevoies' => [],
'adherents' => []
]);
}
}`
This is my ContactController:
`<?php
namespace App\Controller;
use App\Entity\Contact;
use App\Entity\Adherent;
use App\Entity\TypeVoie;
use App\Form\ContactType;
use App\Entity\Utilisateur;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ContactController extends AbstractController
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
#[Route('/administration/contacts', name: 'app_admin_contacts')]
public function admin(): Response
{
$adherents = $this->entityManager->getRepository(Adherent::class)->findAll();
$contacts = [];
foreach ($adherents as $key => $adherent) {
$contacts[] = $this->entityManager->getRepository(Contact::class)->contactsByAdherentId($adherent->getId());
}
return $this->render('contact/index.html.twig', [
'contacts' => $contacts,
]);
}
#[Route('/utilisateur/{user_id}/contacts', name: 'app_user_contacts')]
public function user($user_id): Response
{
$loggedInUser = $this->getUser()->getId();
$user = $this->entityManager->getRepository(Utilisateur::class)->find($user_id);
if ($loggedInUser !== $user->getId()) {
return $this->redirectToRoute('app_login');
}
$association_id = $user->getAssociation()->getId();
$adherents = $this->entityManager->getRepository(Adherent::class)->adherentsByAssocId($association_id);
$contacts = [];
foreach ($adherents as $key => $adherent) {
$contacts[] = $this->entityManager->getRepository(Contact::class)->contactsByAdherentId($adherent->getId());
}
return $this->render('contact/index.html.twig', [
'contacts' => $contacts,
]);
}
#[Route('/contact/ajouter', name: 'app_add_contact')]
public function add(Request $request): Response
{
$user = $this->getUser();
$associationId = $user->getAssociation()->getId();
if ($associationId === 1) {
$typevoies = $this->entityManager->getRepository(TypeVoie::class)->findAll();
$adherents = $this->entityManager->getRepository(Adherent::class)->findAll();
}
if ($associationId > 1) {
$typevoies = $this->entityManager->getRepository(TypeVoie::class)->typevoiesByAssocId($associationId);
$adherents = $this->entityManager->getRepository(Adherent::class)->adherentsByAssocId($associationId);
}
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact, [
'typevoies' => $typevoies,
'adherents' => $adherents
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($contact);
$this->entityManager->flush();
if ($user->getRoles() === 'ROLE_ADMIN') {
return $this->redirectToRoute('app_admin_contacts');
}
return $this->redirectToRoute('app_user_contacts', [
'user_id' => $user->getId()
]);
}
return $this->render('contact/new.html.twig', [
'form' => $form->createView(),
]);
}
#[Route('/contact/modifier/{contactId}', name: 'app_edit_contact')]
public function edit($contactId): Response
{
$user = $this->getUser();
$associationId = $user->getAssociation()->getId();
if ($associationId === 1) {
$typevoies = $this->entityManager->getRepository(TypeVoie::class)->findAll();
$adherents = $this->entityManager->getRepository(Adherent::class)->findAll();
}
if ($associationId > 1) {
$typevoies = $this->entityManager->getRepository(TypeVoie::class)->typevoiesByAssocId($associationId);
$adherents = $this->entityManager->getRepository(Adherent::class)->adherentsByAssocId($associationId);
}
$contact = $this->entityManager->getRepository(Contact::class)->findOneById($contactId);
//dd($contact);
$form = $this->createForm(ContactType::class, $contact, [
'typevoies' => $typevoies,
'adherents' => $adherents
]);
return $this->render('contact/new.html.twig', [
'form' => $form->createView()
]);
}
}`
And this is my Contact entity:
`<?php
namespace App\Entity;
use App\Repository\ContactRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ContactRepository::class)]
class Contact
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 10)]
private ?string $politesse = null;
#[ORM\Column(length: 30)]
private ?string $nom = null;
#[ORM\Column(length: 40)]
private ?string $prenom = null;
#[ORM\Column(length: 20, nullable: true)]
private ?string $tel = null;
#[ORM\Column(length: 20, nullable: true)]
private ?string $mobile = null;
#[ORM\Column(length: 50)]
private ?string $mail = null;
#[ORM\Column(length: 40)]
private ?string $fonction = null;
#[ORM\Column]
private ?bool $annule = null;
#[ORM\Column(length: 5, nullable: true)]
private ?string $numvoie = null;
#[ORM\Column(length: 20, nullable: true)]
private ?string $typevoie = null;
#[ORM\Column(length: 50)]
private ?string $adresse1 = null;
#[ORM\Column(length: 50, nullable: true)]
private ?string $adresse2 = null;
#[ORM\Column(length: 50, nullable: true)]
private ?string $adresse3 = null;
#[ORM\Column(length: 6)]
private ?string $postal = null;
#[ORM\Column(length: 50)]
private ?string $ville = null;
#[ORM\ManyToOne(inversedBy: 'contacts')]
#[ORM\JoinColumn(nullable: false)]
private ?Adherent $adherent = null;
public function getId(): ?int
{
return $this->id;
}
public function getPolitesse(): ?string
{
return $this->politesse;
}
public function setPolitesse(string $politesse): self
{
$this->politesse = $politesse;
return $this;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getPrenom(): ?string
{
return $this->prenom;
}
public function setPrenom(string $prenom): self
{
$this->prenom = $prenom;
return $this;
}
public function getTel(): ?string
{
return $this->tel;
}
public function setTel(?string $tel): self
{
$this->tel = $tel;
return $this;
}
public function getMobile(): ?string
{
return $this->mobile;
}
public function setMobile(?string $mobile): self
{
$this->mobile = $mobile;
return $this;
}
public function getMail(): ?string
{
return $this->mail;
}
public function setMail(string $mail): self
{
$this->mail = $mail;
return $this;
}
public function getFonction(): ?string
{
return $this->fonction;
}
public function setFonction(string $fonction): self
{
$this->fonction = $fonction;
return $this;
}
public function isAnnule(): ?bool
{
return $this->annule;
}
public function setAnnule(bool $annule): self
{
$this->annule = $annule;
return $this;
}
public function getNumvoie(): ?string
{
return $this->numvoie;
}
public function setNumvoie(?string $numvoie): self
{
$this->numvoie = $numvoie;
return $this;
}
public function getTypevoie(): ?string
{
return $this->typevoie;
}
public function setTypevoie(?string $typevoie): self
{
$this->typevoie = $typevoie;
return $this;
}
public function getAdresse1(): ?string
{
return $this->adresse1;
}
public function setAdresse1(string $adresse1): self
{
$this->adresse1 = $adresse1;
return $this;
}
public function getAdresse2(): ?string
{
return $this->adresse2;
}
public function setAdresse2(?string $adresse2): self
{
$this->adresse2 = $adresse2;
return $this;
}
public function getAdresse3(): ?string
{
return $this->adresse3;
}
public function setAdresse3(?string $adresse3): self
{
$this->adresse3 = $adresse3;
return $this;
}
public function getPostal(): ?string
{
return $this->postal;
}
public function setPostal(string $postal): self
{
$this->postal = $postal;
return $this;
}
public function getVille(): ?string
{
return $this->ville;
}
public function setVille(string $ville): self
{
$this->ville = $ville;
return $this;
}
public function getAdherent(): ?Adherent
{
return $this->adherent;
}
public function setAdherent(?Adherent $adherent): self
{
$this->adherent = $adherent;
return $this;
}
}`
What is missing here?
Thanks in advance.
答案1
得分: 3
我通过将以下代码片段添加到表单中成功解决了这个问题:
'multiple' => false,
'expanded' => false,
'mapped' => false
它已添加到表单的 'typevoie' 元素中。
英文:
I managed to resolve the issue by adding the following piece of the code to the form:
'multiple' => false,
'expanded' => false,
'mapped' => false
It has been added to 'typevoie' element of the form.
答案2
得分: 0
worked for symfony 6.3, 6.4 Entitytype form field
'query_builder' => MUST RETURN QueryBuilder OBJECT not real results
solution:
->add('yourAnyField', EntityType::class, [
'class' => Your!!ANY!!EntityClassToFullFillSelectFormChoices::class,
'query_builder' => function (YourEntityClassRepository $repo): QueryBuilder {
return $repo->findGroupOptionsList(17);
},
'choice_label' => 'variableName',
'choice_value' => 'id',
inject repository in FORMTYPE by constructor,
repository MUST RETURN **QueryBuilder** OBJECT not real results
/**
* @param $value
* @return QueryBuilder
*/
public function findByLinkUpstreamManyToOne($value): QueryBuilder
{
$qb = $this->createQueryBuilder('m');
return = $qb
->andWhere('m.linkUpstreamManyToOneEntityFieldName = :val')
->setParameter('val', $value)
->orderBy('m.id', 'ASC')
;
}
note:
-
adding query into repository make it flexible, accessible by any service in the future
-
choice label is verry flexible callback function, you can generate "name" even from many ManyToOne sources [table levels]
'choice_label' => function ($linkUpstreamMegaMenuSection) {
return '[menu] .$linkUpstreamMegaMenuSection->getLinkUpstreamMegaMenu()->getMegaMenuName().' | [section] '
.$linkUpstreamMegaMenuSection->getSectionName();
},
I'm using own notation in entity for field names to describe relations in database may it be also usefull for you
linkUpstreamEntityCalled for ManyToOne [A] <= [B,B,B,B]
linkStreamEntityCalled for OneToMany [A] => [B,B,B,B]
it gives me better view what data i'm looking at programing level
英文:
worked for symfony 6.3, 6.4 Entitytype form field
'query_builder' => MUST RETURN QueryBuilder OBJECT not real results
solution:
->add('yourAnyField', EntityType::class, [
'class' => Your!!ANY!!EntityClassToFullFillSelectFormChoices::class,
'query_builder' => function (YourEntityClassRepository $repo): QueryBuilder {
return $repo->findGroupOptionsList(17);
},
'choice_label' => 'variableName',
'choice_value' => 'id',
inject repository in FORMTYPE by constructor,
repository MUST RETURN **QueryBuilder** OBJECT not real results
/**
* @param $value
* @return QueryBuilder
*/
public function findByLinkUpstreamManyToOne($value): QueryBuilder
{
$qb = $this->createQueryBuilder('m');
return = $qb
->andWhere('m.linkUpstreamManyToOneEntityFieldName = :val')
->setParameter('val', $value)
->orderBy('m.id', 'ASC')
;
}
note:
-
adding query into repository make it flexible, accessible by any service in the future
-
choice label is verry flexible callback function, you can generate "name" even from many ManyToOne sources [table levels]
'choice_label' => function ($linkUpstreamMegaMenuSection) {
return '[menu] .$linkUpstreamMegaMenuSection->getLinkUpstreamMegaMenu()->getMegaMenuName().' | [section] '
.' '.$linkUpstreamMegaMenuSection->getSectionName();
},
I'm using own notation in entity for field names to describe relations in database may it be also usefull for you
linkUpstreamEntityCalled for ManyToOne [A] <= [B,B,B,B]
linkStreamEntityCalled for OneToMany [A] => [B,B,B,B]
it gives me better view what data i'm looking at programing level
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论