I have 2 entities, Product (Produit) and Manufacturer (Fabricant).
When I try to update them from Easy Admin, if I change the Manufacturer on the Product side, all good, it works and the Manufacturer admin does show the right amount of child products.
However, if I do it the other way around - choosing child products from the Manufacturer admin - it doesn't save it in the database. It does save the name, but not the child list.
A few topics here and there indicate that I have to make sure that in the addProduct function, I also act on the product with a $product->setManufacturer($this); ... which I did (see code below).
Others mentioned that in the admin configuration, I should put the by_reference option to false. Which I also did. Yet no success.
Another suggestion was to make sure that the cascading was right between the 2 entities, I've put it to "all" until I can figure out what's wrong, but it still doesn't work. No error message, no warning, it even saves the other fields, but not this one. Any idea ?
Product :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ProduitRepository")
*/
class Produit
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $nom;
/**
* @ORM\ManyToOne(targetEntity="Fabricant", inversedBy="produits", cascade="all")
*/
private $fabricant;
public function __toString()
{
return ($this->nom != null) ? $this->nom : '';
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getNom()
{
return $this->nom;
}
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
public function getFabricant()
{
return $this->fabricant;
}
public function setFabricant($fabricant)
{
$this->fabricant = $fabricant;
return $this;
}
}
Manufacturer :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity(repositoryClass="App\Repository\FabricantRepository")
*/
class Fabricant
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $nom;
/**
* @ORM\OneToMany(targetEntity="Produit", mappedBy="fabricant", cascade="all")
*/
private $produits;
public function __toString()
{
return ($this->nom != null) ? $this->nom : '';
}
public function __construct()
{
$this->produits = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getNom()
{
return $this->nom;
}
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
public function getProduits()
{
return $this->produits;
}
public function addProduit(Produit $produit)
{
if ($this->produits->contains($produit)) {
return;
}
$this->produits[] = $produit;
$produit->setFabricant($this);
return $this;
}
public function removeProduit($produit)
{
$this->produits->removeElement($produit);
$produit->setFabricant(null);
}
}
Easy Admin yaml config :
easy_admin:
entities:
Produit:
class: App\Entity\Produit
list:
fields:
- id
- nom
- fabricant
new:
fields:
- nom
- { property: 'fabricant', type_options: { 'by_reference': false } }
Fabricant:
class: App\Entity\Fabricant
list:
fields:
- id
- nom
- produits
new:
fields:
- nom
- { property: 'produits', type_options: { by_reference: false } }
edit:
fields:
- nom
- { property: 'produits', type_options: { multiple: true, by_reference: false } }
Cause is bug in EasyAdmin controller which calls flush() with concrete $entity, so other changes are not persisted. You can wait for new release or extend AdminController and override methods.
Change of control class:
easy_admin_bundle:
resource: 'App\Controller\AdminController'
prefix: /admin
type: annotation
Extended admin controller:
<?php
namespace App\Controller;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
class AdminController extends BaseAdminController
{
protected function persistEntity($entity)
{
$this->em->persist($entity);
$this->em->flush();
}
protected function updateEntity($entity)
{
$this->em->flush();
}
protected function removeEntity($entity)
{
$this->em->remove($entity);
$this->em->flush();
}
}
The issue appears very often and I just ran into it myself. Here is my solution without overriding any controller action:
For anyone who is on EasyAdminBundle v1.17.08 - v1.17.22
you should upgrade first. Apparently Issue #1679 introduced a bug that results in this error.
The next step is to make sure the cascade
option in the owning entity is set:
@ORM\OneToMany(targetEntity="PageBlock", mappedBy="page", cascade="all", orphanRemoval=true)
Also set the by_reference
option in your form:
# in your easy_admin config block...
- property: 'blocks'
type: 'collection'
type_options:
entry_type: ...PageBlockType
by_reference: false
The last but not least I was missing the add
and remove
methods in my parent entity. Make also sure the naming is correct. So for the property
named $block
use this:
public function addBlock(PageBlock $block) : void
{
$block->setPage($this);
$this->blocks->add($block);
}
public function removeBlock(PageBlock $block) : void
{
$block->setPage(null);
$this->blocks->remove($block);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With