传递给 Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader::getIdValue() 的参数 1 必须是一个对象或 null, int 给定

问题描述 投票:0回答:4

我是 Symfony 的新手。我遵循了一些tutorials,尝试学习相关选择,因此我使用 DestinationFormType 和 DestinationController 来保存 Destination。 JS 部分运行良好,但现在当我尝试保存实体时会抛出下一个异常:

传递给 Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader::getIdValue() 的参数 1 必须是一个对象或给定的 null、int,在第 200 行的 endor\symfony orm\ChoiceList\ArrayChoiceList.php 中调用

奇怪的部分是它似乎试图转换一个不需要转换的值(191)(堆栈调用顶部):

针对国家/地区实体抛出错误。这是我的 DestinationFormType

<?php namespace App\Form; use App\Entity\City; use App\Entity\Country; use App\Entity\Destination; use App\Entity\DestinationCategory; use App\Entity\DestinationSubcategory; use App\Entity\Region; use App\Entity\State; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class DestinationFormType extends AbstractType { /** @var EntityManagerInterface */ private $em; /** * @param EntityManagerInterface $em */ public function __construct(EntityManagerInterface $em) { $this->em = $em; } /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') ->add('coordinates') ->add('kidsCost') ->add('adultsCost') ->add('description') ; $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData')); $builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit')); } /** * @param OptionsResolver $resolver */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => Destination::class ]); } /** * @param FormEvent $event */ public function onPreSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); /** @var Region $region */ $region = $this->em ->getRepository(Region::class) ->find($data['region']); /** @var Country $country */ $country = $this->em ->getRepository(Country::class) ->find($data['country']); /** @var State $state */ $state = $this->em ->getRepository(State::class) ->find($data['state']); /** @var City $city */ $city = $this->em ->getRepository(City::class) ->find($data['city']); /** @var DestinationCategory $city */ $category = $this->em ->getRepository(DestinationCategory::class) ->find($data['category']); /** @var DestinationCategory $city */ $subcategory = $this->em ->getRepository(DestinationSubcategory::class) ->find($data['subcategory']); $this->addLocationDropdowns($form, $region, $country, $state, $city); $this->addCategoryDropdowns($form, $category, $subcategory); } /** * @param FormEvent $event */ public function onPreSetData(FormEvent $event) { /** @var Destination $destination */ $destination = $event->getData(); $form = $event->getForm(); $category = $destination && $destination->getCategory() ? $destination->getCategory() : null; $subcategory = $destination && $destination->getSubcategory() ? $destination->getSubcategory() : null; $region = $destination && $destination->getRegion() ? $destination->getRegion() : null; $country = $destination && $destination->getCountry() ? $destination->getCountry() : null; $state = $destination && $destination->getState() ? $destination->getState() : null; $city = $destination && $destination->getCity() ? $destination->getCity() : null; $this->addLocationDropdowns($form, $region, $country, $state, $city); $this->addCategoryDropdowns($form, $category, $subcategory); } /** * @param FormInterface $form * @param Region|null $region * @param Country|null $country * @param State|null $state * @param City|null $city */ private function addLocationDropdowns(FormInterface $form, ?Region $region, ?Country $country, ?State $state, ?City $city) { $this->addRegionDropDown($form, $region); $this->addCountryDropdown($form, $region, $country); $this->addStateDropdown($form, $country, $state); $this->addCityDropdown($form, $state, $city); } /** * @param FormInterface $form * @param Region|null $region */ private function addRegionDropDown(FormInterface $form, ?Region $region) { $form->add('region', EntityType::class,[ 'required' => true, 'data' => $region, 'placeholder' => 'Select a Region...', 'class' => Region::class ]); } /** * @param FormInterface $form * @param Region|null $region * @param Country|null $country */ private function addCountryDropdown(FormInterface $form, ?Region $region, ?Country $country) { $countries = array(); if ($region) { $countryRepository = $this->em->getRepository(Country::class); $countries = $countryRepository->findByRegionId($region->getId()); } $form->add('country', EntityType::class, [ 'required' => true, 'data' => $country, 'placeholder' => 'Select a Region first ...', 'class' => Country::class, 'choices' => $countries ]); } /** * @param FormInterface $form * @param Country|null $country * @param State|null $state */ private function addStateDropdown(FormInterface $form, ?Country $country, ?State $state) { $states = array(); if ($country) { $stateRepository = $this->em->getRepository(State::class); $states = $stateRepository->findByCountryId($country->getId()); } $form->add('state', EntityType::class, [ 'required' => true, 'data' => $state, 'placeholder' => 'Select a Country first ...', 'class' => State::class, 'choices' => $states ]); } /** * @param FormInterface $form * @param State|null $state * @param City|null $city */ private function addCityDropdown(FormInterface $form, ?State $state, ?City $city) { $cities = array(); if ($state) { $cityRepository = $this->em->getRepository(City::class); $cities = $cityRepository->findByStateId($state->getId()); } $form->add('city', EntityType::class, [ 'required' => true, 'data' => $city, 'placeholder' => 'Select a State first ...', 'class' => State::class, 'choices' => $cities ]); } /** * @param FormInterface $form * @param DestinationCategory|null $category * @param DestinationSubcategory|null $subcategory */ private function addCategoryDropdowns(FormInterface $form, ?DestinationCategory $category, ?DestinationSubcategory $subcategory) { $this->addCategoryDropDown($form, $category); $this->addSubcategoryDropDown($form, $category, $subcategory); } /** * @param FormInterface $form * @param DestinationCategory|null $category */ private function addCategoryDropDown(FormInterface $form, ?DestinationCategory $category) { $form->add('category', EntityType::class,[ 'required' => true, 'data' => $category, 'placeholder' => 'Select a Category...', 'class' => DestinationCategory::class ]); } /** * @param FormInterface $form * @param DestinationCategory|null $category * @param DestinationSubcategory|null $subcategory */ private function addSubcategoryDropDown(FormInterface $form, ?DestinationCategory $category, ?DestinationSubcategory $subcategory) { $subcategories = array(); if ($category) { $countryRepository = $this->em->getRepository(DestinationSubcategory::class); $subcategories = $countryRepository->findByCategoryId($category->getId()); } $form->add('subcategory', EntityType::class, [ 'required' => true, 'data' => $subcategory, 'placeholder' => 'Select a Category first ...', 'class' => DestinationSubcategory::class, 'choices' => $subcategories ]); } }

这是我的目的地控制器

<?php namespace App\Controller; use App\Entity\Destination; use App\Form\DestinationFormType; use App\Repository\DestinationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class DestinationController extends AbstractController { /** * @Route("admin/destination/new", name="admin_destination_new") * * @param EntityManagerInterface $em * @param Request $request * * @return Response */ public function new(EntityManagerInterface $em, Request $request) { $form = $this->createForm(DestinationFormType::class); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { /** @var Destination $destination */ $destination = $form->getData(); $em->persist($destination); $em->flush(); $this->addFlash('success', 'Destination created'); $this->redirectToRoute('admin_destination_list'); } return $this->render('destination/new.html.twig', [ 'destForm' => $form->createView() ]); } /** * @Route("admin/destination/{id}/edit", name="admin_destination_edit") * * @param Destination $destination * @param EntityManagerInterface $em * @param Request $request * * @return Response */ public function edit(Destination $destination, EntityManagerInterface $em, Request $request) { $form = $this->createForm(DestinationFormType::class, $destination); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em->persist($destination); $em->flush(); $this->addFlash('success', 'Destiny updated'); $this->redirectToRoute('admin_destination_list'); } return $this->render('destination/edit.html.twig', [ 'destForm' => $form->createView() ]); } /** * @Route("admin/destination", name="admin_destination_list") * @param DestinationRepository $destRepo * * @return Response */ public function list(DestinationRepository $destRepo){ /** @var Destination $destinations */ $destinations = $destRepo->findAll(); return $this->render('destination/list.html.twig', [ 'destinations' => $destinations ]); } }

这是我的目标实体

<?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity; use Gedmo\Timestampable\Traits\TimestampableEntity; use Gedmo\Mapping\Annotation as Gedmo; /** * @ORM\Entity(repositoryClass="App\Repository\DestinationRepository") */ class Destination { use TimestampableEntity; use SoftDeleteableEntity; /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string", length=150) */ private $name; /** * @ORM\Column(type="string", length=150, nullable=true) */ private $coordinates; /** * @ORM\Column(type="string", length=150, unique=true) * @Gedmo\Slug(fields={"name"}) */ private $slug; /** * @ORM\Column(type="decimal", precision=8, scale=2, nullable=true) */ private $kidsCost; /** * @ORM\Column(type="decimal", precision=8, scale=2, nullable=true) */ private $adultsCost; /** * @ORM\ManyToMany(targetEntity="App\Entity\Package", mappedBy="destinations") */ private $packages; /** * @ORM\Column(type="text", nullable=true) */ private $description; /** * @ORM\Column(type="string", length=255, nullable=true) */ private $address; /** * @ORM\ManyToOne(targetEntity="App\Entity\City") * @ORM\JoinColumn(nullable=false) */ private $city; /** * @ORM\ManyToOne(targetEntity="App\Entity\State") * @ORM\JoinColumn(nullable=false) */ private $state; /** * @ORM\ManyToOne(targetEntity="App\Entity\Region", inversedBy="destinations") * @ORM\JoinColumn(nullable=false) */ private $region; /** * @ORM\ManyToOne(targetEntity="App\Entity\Country", inversedBy="destinations") * @ORM\JoinColumn(nullable=false) */ private $country; /** * @ORM\ManyToOne(targetEntity="App\Entity\DestinationCategory", inversedBy="destinations") * @ORM\JoinColumn(nullable=false) */ private $category; /** * @ORM\ManyToOne(targetEntity="App\Entity\DestinationSubcategory", inversedBy="destinations") * @ORM\JoinColumn(nullable=false) */ private $subcategory; public function __construct() { $this->packages = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getName(): ?string { return $this->name; } public function setName(string $name): self { $this->name = $name; return $this; } public function getCoordinates(): ?string { return $this->coordinates; } public function setCoordinates(?string $coordinates): self { $this->coordinates = $coordinates; return $this; } public function getSlug(): ?string { return $this->slug; } public function setSlug(string $slug): self { $this->slug = $slug; return $this; } public function getKidsCost(): ?string { return $this->kidsCost; } public function setKidsCost(?string $kidsCost): self { $this->kidsCost = $kidsCost; return $this; } public function getAdultsCost(): ?string { return $this->adultsCost; } public function setAdultsCost(?string $adultsCost): self { $this->adultsCost = $adultsCost; return $this; } /** * @return Collection|Package[] */ public function getPackages(): Collection { return $this->packages; } public function addPackage(Package $package): self { if (!$this->packages->contains($package)) { $this->packages[] = $package; $package->addDestination($this); } return $this; } public function removePackage(Package $package): self { if ($this->packages->contains($package)) { $this->packages->removeElement($package); $package->removeDestination($this); } return $this; } public function getDescription(): ?string { return $this->description; } public function setDescription(?string $description): self { $this->description = $description; return $this; } public function getAddress(): ?string { return $this->address; } public function setAddress(?string $address): self { $this->address = $address; return $this; } public function getCity(): ?City { return $this->city; } public function getState(): ?State { return $this->getCity() ? $this->getCity()->getState() : null; } public function getCountry(): ?Country { return $this->getCity()? $this->getState()->getCountry() : null; } public function getRegion() : ?Region { return $this->getCity()? $this->getCountry()->getRegion() : null; } public function setCity(?City $city): self { $this->city = $city; return $this; } public function setState(?State $state): self { $this->state = $state; return $this; } public function setRegion(?Region $region): self { $this->region = $region; return $this; } public function setCountry(?Country $country): self { $this->country = $country; return $this; } public function getCategory(): ?DestinationCategory { return $this->category; } public function setCategory(?DestinationCategory $category): self { $this->category = $category; return $this; } public function getSubcategory(): ?DestinationSubcategory { return $this->subcategory; } public function setSubcategory(?DestinationSubcategory $subcategory): self { $this->subcategory = $subcategory; return $this; } }

有人可以指出我正确的方向来解决这个问题吗?

诗。我正在使用 symfony 5.0.7。

提前致谢

php symfony doctrine
4个回答
2
投票

$countries = $countryRepository->findByRegionId($region->getId());

你可能认为返回的是国家数组,但实际上它是 JS 的助手,只返回 id 和 name

/** * @param int $regionId * @return array */ public function findByRegionId(int $regionId) { return $this->createQueryBuilder('c') ->select(['c.id', 'c.name']) ->where('c.region = :id') ->orderBy('c.name') ->setParameter('id', $regionId) ->getQuery() ->execute(); }

所以以防万一其他人遇到这个问题: $choices 需要一个对象数组,而不是带有 id 和 name 的数组,所以我像这样修改了我的 addCountryDropDown 方法

private function addCountryDropdown(FormInterface $form, ?Region $region, ?Country $country) { $countries = array(); if ($region) { $countryRepository = $this->em->getRepository(Country::class); $countries = $countryRepository->findBy([ 'region' => $region->getId() ]); } $form->add('country', EntityType::class, [ 'required' => true, 'data' => $country, 'placeholder' => 'Select a Region first ...', 'class' => Country::class, 'choices' => $countries ]); }



0
投票

我通过在 User 实体中添加 getRolesObjects() 解决了这个问题:

public function getRolesObjects(): array { if(is_array($this->roles)) { return $this->roles; } else if($this->roles && ($this->roles instanceof Collection)) { return $this->roles->toArray(); } else { return []; } }

并在 FormType 中添加自定义 getter:

$builder ->add('firstName', TextType::class) ->add('lastName', TextType::class) ->add('email', TextType::class) ->add('roles', EntityType::class, [ 'class' => Role::class, 'multiple' => true, 'getter' => function (User $user, FormInterface $form): array { return $user->getRolesObjects(); } ]);



0
投票

事实证明,我试图将数组传递给未设置为接受多项选择的

ChoiceType

我希望它可以挽救某人几分钟的生命!


0
投票

'query_builder' => 必须返回

QueryBuilder 对象不是真实结果 解决方案:

->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') ; }

注:

    将查询添加到存储库中使其灵活,将来可以由任何服务访问
  1. 选择标签是非常灵活的回调函数,您甚至可以从许多ManyToOne源[表级别]生成“名称”
  2. 'choice_label' => 函数 ($linkUpstreamMegaMenuSection) { 返回“[menu] .$linkUpstreamMegaMenuSection->getLinkUpstreamMegaMenu()->getMegaMenuName()。” | [部分] ' .' '.$linkUpstreamMegaMenuSection->getSectionName(); },

我在实体中使用自己的符号来表示字段名称来描述数据库中的关系

可能对您也有用

linkUpstream

EntityCalled for ManyToOne [A] <= [B,B,B,B]

linkStream

EntityCalled for OneToMany [A] => [B,B,B,B] 它让我更好地查看我正在查看编程级别的数据

© www.soinside.com 2019 - 2024. All rights reserved.