Here some context information: I'm building a Symfony2 application with Doctrine2 and FOSRestBundle.
My problem: I want to be able to create a parent with his children with just one JSON and one database access.
My JSON looks like this:
{
"name": "TEST_NAME",
"info": "TEST_INFO",
"cmts": [
{
"cmt": "CMT1",
"info": "INFO1"
},
{
"cmt": "CMT2",
"info": "INFO2"
},
{
"cmt": "CMT3",
"info": "INFO3"
}
]
}
Here is my TEST entity:
<?php
namespace App\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Test
*
* @ORM\Table(name="Test")
* @ORM\Entity(repositoryClass="App\Bundle\DemoBundle\Entity\TestRepository")
*/
class Test
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
* @Assert\NotBlank()
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="info", type="string", length=255, nullable=true)
*/
private $info;
/**
* @ORM\OneToMany(targetEntity="TestCmt", mappedBy="test", fetch="EAGER", orphanRemoval=true, cascade={"merge", "remove", "persist"})
*/
protected $cmts;
/**
* Constructor
*/
public function __construct()
{
$this->cmts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add cmts
*
* @param \App\Bundle\DemoBundle\Entity\TestCmt $cmts
* @return Test
*/
public function addCmt(\App\Bundle\DemoBundle\Entity\TestCmt $cmts)
{
$this->cmts[] = $cmts;
return $this;
}
/**
* Remove cmts
*
* @param \App\Bundle\DemoBundle\Entity\TestCmt $cmts
*/
public function removeCmt(\App\Bundle\DemoBundle\Entity\TestCmt $cmts)
{
$this->cmts->removeElement($cmts);
}
/**
* Get cmts
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCmts()
{
return $this->cmts;
}
// other getters/setters...
}
And my TESTCMT entity:
<?php
namespace App\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TestCmt
*
* @ORM\Table(name="TestCmt")
* @ORM\Entity(repositoryClass="App\Bundle\DemoBundle\Entity\TestCmtRepository")
*/
class TestCmt
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="cmt", type="string", length=255)
*/
private $cmt;
/**
* @var string
*
* @ORM\Column(name="info", type="string", length=255, nullable=true)
*/
private $info;
/**
* @var Test
*
* @ORM\ManyToOne(targetEntity="Test", inversedBy="cmts")
* @ORM\JoinColumn(name="test_id", referencedColumnName="id")
**/
private $test;
/**
* Set test
*
* @param \App\Bundle\DemoBundle\Entity\Test $test
* @return TestCmt
*/
public function setTest(\App\Bundle\DemoBundle\Entity\Test $test = null)
{
$this->test = $test;
return $this;
}
/**
* Get test
*
* @return \App\Bundle\DemoBundle\Entity\Test
*/
public function getTest()
{
return $this->test;
}
}
And finaly my postTestAction():
public function postTestAction(Request $request)
{
$entity = $this->deserialize($request, 'App\DemoBundle\Entity\Test');
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $entity;
}
When I send the JSON, TEST and TESTCMTs are created. Nevertheless, all "test_id" from the created TESTCMTs are "null"... And that's my problem!
EDIT: with SQL Server Profiler, I can see that Doctrine make that Transact SQL request:
INSERT INTO TESTCMT (test_id, cmt, info) VALUES (null, 'CMT', 'INFO')
I don't know why Doctrine can't send the test_id... TEST is created before TESTCMT, so "test_id" should be reachable for Doctrine to create the associate TESTCMTs.
Can someone helped me to fix it? :)
Remove @ORM\GeneratedValue(strategy="AUTO") and it won't let the DB generate a new id for the Entity