I have a problem with the SonataAdminBunle in combination with symfony 2.2. I have a Project entity and a ProjectImage entity and specified a One-to-Many relationship between these two like so:
class Project
{
/**
* @ORM\OneToMany(targetEntity="ProjectImage", mappedBy="project", cascade={"all"}, orphanRemoval=true)
*/
private $images;
}
class ProjectImage
{
/**
* @ORM\ManyToOne(targetEntity="Project", inversedBy="images")
* @ORM\JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
}
I've configured the ProjectAdmin and ProjectImageAdmin:
class ProjectAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title')
->add('website')
->add('description', 'textarea')
->add('year')
->add('tags')
->add('images', 'sonata_type_collection', array(
'by_reference' => false
), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'id',
))
;
}
}
class ProjectImageAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('file', 'file', array(
'required' => false
))
;
}
}
The problem is that in the project_image table in the database the project_id is not saved, while all other data is and also the image is saved. Couldn't find a working answer anywhere else.
Although unrelated, I'd slighty tweak your One-to-Many annotation:
class Project
{
/**
* @ORM\OneToMany(targetEntity="ProjectImage", mappedBy="project", cascade={"persist"}, orphanRemoval=true)
* @ORM\OrderBy({"id" = "ASC"})
*/
private $images;
}
Back on track, your annotations and Sonata Admin forms look fine, so I'm pretty sure you're missing one of those methods in your Project entity class:
public function __construct() {
$this->images = new \Doctrine\Common\Collections\ArrayCollection();
}
public function setImages($images)
{
if (count($images) > 0) {
foreach ($images as $i) {
$this->addImage($i);
}
}
return $this;
}
public function addImage(\Acme\YourBundle\Entity\ProjectImage $image)
{
$image->setProject($this);
$this->images->add($image);
}
public function removeImage(\Acme\YourBundle\Entity\ProjectImage $image)
{
$this->images->removeElement($image);
}
public function getImages()
{
return $this->Images;
}
And in your Admin class:
public function prePersist($project)
{
$this->preUpdate($project);
}
public function preUpdate($project)
{
$project->setImages($project->getImages());
}
Since some things have changed with Symfony form collection now adding the addChild() and removeChild() with the by_reference option set to false automatically persist the Collection and set the ID on the inverse side as expected.
Here is a full working version: https://gist.github.com/webdevilopers/1a01eb8c7a8290d0b951
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('childs', 'sonata_type_collection', array(
'by_reference' => false
), array(
'edit' => 'inline',
'inline' => 'table'
))
;
}
The addChild() method must contain the setter for the parent on the child:
public function addChild($child)
{
$child->setParent($this); // !important
$this->childs[] = $child;
return $this;
}
You ca do it directly in the preUpdate function
public function prePersist($societate)
{
$this->preUpdate($societate);
}
public function preUpdate($societate)
{
$conturi = $societate->getConturi();
if (count($conturi) > 0) {
foreach ($conturi as $cont) {
$cont->setSocietate($societate);
}
}
}
the simplest solution is, and naturally replace your variable names; this works for me: 'by_reference' => false
as follows:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('articles', EntityType::class, array(
'class' => 'EboxoneAdminBundle:Article',
'required' => false,
'by_reference' => false,
'multiple' => true,
'expanded' => false,
))
->add('formInputs', CollectionType::class, array(
'entry_type' => FormInputType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
;
}
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