Reputation: 734
I have a Many to Many relationship between my Entities: PurchaseOrder
and Supplier
. When I want do add a Supplier
to an order in my Symfony project, I always get this error message:
Property "suppliers" is not public in class "Acme\AppBundle\Entity\PurchaseOrder". Maybe you should create the method "setSuppliers()"?
When I make a setSuppliers()
function by myself in the PurchaseOrder
Entity:
public function setSuppliers(\Acme\AppBundle\Entity\Supplier $suppliers )
{
$this->suppliers = $suppliers;
return $this;
}
I get this error message:
Catchable Fatal Error: Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be of the type array, object given, called in /var/www/symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 519 and defined in /var/www/symfony/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php line 47
Any ideas?
/**
* @Route("order/{id}/supplieradd", name="order_supplieradd")
* @Secure(roles="ROLE_ADMIN")
*/
public function newSupplierAction(Request $request, $id)
{
$purchaseOrder = $this->getDoctrine()
->getRepository('AcmeAppBundle:PurchaseOrder')
->find($id);
if (!$purchaseOrder) {
throw $this->createNotFoundException(
'No order found for id '.$id
);
}
$form = $this->createForm(new AddSupplierType(), $purchaseOrder);
// process the form on POST
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($purchaseOrder);
$em->flush();
return new Response('Added Supplier to Order with ID '.$articleOrder->getId());
}
}
return $this->render('AcmeAppBundle:BasicData:newSupplier.html.twig', array(
'form' => $form->createView(),
'id' => $id,
));
}
And my AddSupplierType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('suppliers', 'entity', array(
'class' => 'AcmeAppBundle:Supplier',
'property' => 'name',
));
}
Some parts of the PurchaseOrder
and Supplier
entities:
class PurchaseOrder{
...
/**
* @ORM\ManyToMany(targetEntity="Supplier", mappedBy="purchaseOrders")
*/
private $suppliers;
public function __construct()
{
$this->suppliers = new ArrayCollection();
}
/**
* Add suppliers
*
* @param \Acme\AppBundle\Entity\Supplier $suppliers
* @return PurchaseOrder
*/
public function addSupplier(\Acme\AppBundle\Entity\Supplier $suppliers)
{
$this->suppliers[] = $suppliers;
return $this;
}
/**
* Remove suppliers
*
* @param \Acme\AppBundle\Entity\Supplier $suppliers
*/
public function removeSupplier(\Acme\AppBundle\Entity\Supplier $suppliers)
{
$this->suppliers->removeElement($suppliers);
}
/**
* Get suppliers
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getSuppliers()
{
return $this->suppliers;
}
}
class Supplier{
...
/**
* @ORM\ManyToMany(targetEntity="PurchaseOrder", inversedBy="suppliers")
* @ORM\JoinTable(name="suppliers_purchaseOrders")
*/
private $purchaseOrders;
}
New add remove set methods:
/**
* Add supplier
*
* @param \Acme\AppBundle\Entity\Supplier $supplier
* @return PurchaseOrder
*/
public function addSupplier(\Acme\AppBundle\Entity\Supplier $supplier)
{
$this->suppliers->add($supplier);
return $this;
}
/**
* Remove supplier
*
* @param \Acme\AppBundle\Entity\Supplier $supplier
*/
public function removeSupplier(\Acme\AppBundle\Entity\Supplier $supplier)
{
$this->suppliers->removeElement($supplier);
}
public function setSuppliers($supplier)
{
if ( is_array($supplier) ) {
$this->suppliers = $supplier ;
} else {
$this->suppliers->clear() ;
$this->suppliers->add($supplier) ;
}
}
Upvotes: 3
Views: 8989
Reputation: 5158
Problems:
Grammatically incorrect method name and its argument:
public function addSupplier(\Acme\AppBundle\Entity\Supplier $suppliers)
method says addSupplier (singular) but you are accepting supplierS (plural)
You need refactoring on this method to be:
public function addSupplier(Supplier $supplier)
{
$this->suppliers->add($supplier) ;
}
also:
public function removeSupplier(Supplier $supplier)
{
$this->suppliers->removeElement($supplier) ;
}
Getter and setter method will work if you do it like my answer on: set multiple='false' in a form in a many to many relation symfony2
Symfony will find add...() and remove...() methods by itself. So if relation is "suppliers", it will find addSupplier. Or if relation is "categories", it will find addCategory() and removeCategory().
Upvotes: 10
Reputation: 188
Shouldn't your setSupliers
method take an ArrayCollection
as the first argument?
public function setSuppliers(ArrayCollection $suppliers )
{
$this->suppliers = $suppliers;
return $this;
}
As you initalized it as ArrayCollection
in your constructor. With your setSuppliers
method
you will convert your ArrayCollection
to one single Supplier
Object.
Your form will return one single selected Suplier
Object. If this is realy what you want, why don't you use a OnyToMany realtionship?
Otherwise you could add the multiple option to your form field. Then multiple Suplier objects can be returned as array.
Upvotes: -1