the error is:
Could not determine access type for property "offerOrders" in class "App\Form\OrderType": Neither the property "offerOrders" nor one of the methods "addOfferOrder()"/"removeOfferOrder()", "setOfferOrders()", "offerOrders()", "__set()" or "__call()" exist and have public access in class "App\Form\OrderType"..
PhotoSession Class
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\PhotoSessionRepository")
*/
class PhotoSession
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToOne(targetEntity="App\Entity\Order", inversedBy="photoSession", cascade={"persist", "remove"})
* @ORM\JoinColumn(nullable=false)
*/
private $purchaseOrder;
Order Class
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\OrderRepository")
* @ORM\Table(name="`order`")
*/
class Order
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToOne(targetEntity="App\Entity\PhotoSession", mappedBy="purchaseOrder", cascade={"persist", "remove"})
*/
private $photoSession;
/**
* @ORM\OneToMany(targetEntity="App\Entity\OfferOrder", mappedBy="purchaseOrder", cascade={"persist"})
*/
private $offerOrders;
public function __construct()
{
$this->offerOrders = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getPhotoSession(): ?PhotoSession
{
return $this->photoSession;
}
public function setPhotoSession(PhotoSession $photoSession): self
{
$this->photoSession = $photoSession;
// set the owning side of the relation if necessary
if ($photoSession->getPurchaseOrder() !== $this) {
$photoSession->setPurchaseOrder($this);
}
return $this;
}
/**
* @return Collection|OfferOrder[]
*/
public function getOfferOrders(): Collection
{
return $this->offerOrders;
}
public function addOfferOrder(OfferOrder $offerOrder): self
{
if (!$this->offerOrders->contains($offerOrder)) {
$this->offerOrders[] = $offerOrder;
$offerOrder->setPurchaseOrder($this);
}
return $this;
}
public function removeOfferOrder(OfferOrder $offerOrder): self
{
if ($this->offerOrders->contains($offerOrder)) {
$this->offerOrders->removeElement($offerOrder);
// set the owning side to null (unless already changed)
if ($offerOrder->getPurchaseOrder() === $this) {
$offerOrder->setPurchaseOrder(null);
}
}
return $this;
}
}
offerOrder Class
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\OfferOrderRepository")
*/
class OfferOrder
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Offer", inversedBy="offerOrders")
* @ORM\JoinColumn(nullable=false)
*/
private $offer;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Order", inversedBy="offerOrders")
* @ORM\JoinColumn(nullable=false)
*/
private $purchaseOrder;
/**
* @ORM\Column(type="float", nullable=true)
*/
private $quantity;
/**
* @ORM\Column(type="float", nullable=true)
*/
private $totalPriceHt;
public function getId(): ?int
{
return $this->id;
}
public function getOffer(): ?Offer
{
return $this->offer;
}
public function setOffer(?Offer $offer): self
{
$this->offer = $offer;
return $this;
}
public function getPurchaseOrder(): ?Order
{
return $this->purchaseOrder;
}
public function setPurchaseOrder(?Order $purchaseOrder): self
{
$this->purchaseOrder = $purchaseOrder;
return $this;
}
public function getQuantity(): ?float
{
return $this->quantity;
}
public function setQuantity(?float $quantity): self
{
$this->quantity = $quantity;
return $this;
}
public function getTotalPriceHt(): ?float
{
return $this->totalPriceHt;
}
public function setTotalPriceHt(?float $totalPriceHt): self
{
$this->totalPriceHt = $totalPriceHt;
return $this;
}
}
offer class
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\OfferRepository")
*/
class Offer
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="float")
*/
private $price;
/**
* @var Tag
* @ORM\ManyToOne(targetEntity="App\Entity\Tag")
* @ORM\JoinColumn(nullable=false)
*/
private $tag;
/**
* @var integer|null
* @ORM\Column(type="integer")
*/
private $version = 0;
/**
* @ORM\OneToMany(targetEntity="App\Entity\OfferOrder", mappedBy="offer")
*/
private $offerOrders;
public function __construct()
{
$this->offerOrders = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getPrice(): ?float
{
return $this->price;
}
public function setPrice(float $price): self
{
$this->price = $price;
return $this;
}
/**
* @return Tag|null
*/
public function getTag(): ?Tag
{
return $this->tag;
}
/**
* @param Tag $tag
* @return Offer
*/
public function setTag(Tag $tag): self
{
$this->tag = $tag;
return $this;
}
/**
* @return int|null
*/
public function getVersion(): ?int
{
return $this->version;
}
/**
* @param int|null $version
* @return Offer
*/
public function setVersion(?int $version): self
{
$this->version = $version;
return $this;
}
/**
* @return Collection|OfferOrder[]
*/
public function getOfferOrders(): Collection
{
return $this->offerOrders;
}
public function addOfferOrder(OfferOrder $offerOrder): self
{
if (!$this->offerOrders->contains($offerOrder)) {
$this->offerOrders[] = $offerOrder;
$offerOrder->setOffer($this);
}
return $this;
}
public function removeOfferOrder(OfferOrder $offerOrder): self
{
if ($this->offerOrders->contains($offerOrder)) {
$this->offerOrders->removeElement($offerOrder);
// set the owning side to null (unless already changed)
if ($offerOrder->getOffer() === $this) {
$offerOrder->setOffer(null);
}
}
return $this;
}
}
SessionPhotoType
<?php
namespace App\Form;
use App\Entity\Family;
use App\Entity\PhotoSession;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PhotoSessionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
->add('family', EntityType::class, [
'class' => Family::class,
'choice_label' => 'name',
])
->add('purchaseOrder', OrderType::class, [
'data_class' => OrderType::class
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PhotoSession::class,
]);
}
}
OrderType
<?php
namespace App\Form;
use App\Entity\Order;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class OrderType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('offerOrders', CollectionType::class, [
'entry_type' => OfferOrderType::class,
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
])
->add('totalPriceHt')
->add('tva')
->add('finalPrice')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Order::class,
]);
}
}
OfferOrderType
class OfferOrderType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder
->add('offer', EntityType::class, [
'class' => Offer::class,
'choice_label' => function(Offer $offer) {
return sprintf('%s %f €', $offer->getTag()->getName(), $offer->getPrice());
},
'placeholder' => 'Choissiez une offre'
])
->add('quantity', NumberType::class)
->add('totalPriceHt', NumberType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'widget' => 'single_text',
'data_class' => OfferOrder::class,
]);
}
}
I'm sorry for the long code blocks, but for the people who will try to solve the bug I think that there is the necessary one. The error is returned when I submit the form. The question I ask myself is why symfony is looking for accessors in the App\Form\OrderType class?
I put dumps everywhere in PropertyAccessor.php PropertyPathMapper.php and vendor/symfony/form/Form.php, and when it goes here:
if (FormUtil::isEmpty($viewData)) {
$emptyData = $this->config->getEmptyData();
if ($emptyData instanceof \Closure) {
$emptyData = $emptyData($this, $viewData);
}
$viewData = $emptyData;
dump($viewData);
}
in Form.php it sets $viewData to App\Form\OrderType
but I don't know why
The answer was:
For the form to pass, it was necessary to change purchaseOrder in photoSessionType like this:
-> add ('purchaseOrder', OrderType :: class)
Thanks again to @Ihor Kostrov
Try to change
->add('purchaseOrder', OrderType::class, [
'data_class' => OrderType::class
])
To
->add('purchaseOrder', OrderType::class, [
'data_class' => Order::class
])
Or just remove data_class option