I'm working on a ZF2/Apigility application using Doctrine v2.4.2
.
The model structure looks like this: an
Asset
has
an
Attachment
(so, it's a 1:1
relationship):
The problem is that I cannot persist an Asset
with an embedded Attachment
and get the error
23000, 1048, Column 'attachment_linkassetuuid' cannot be null
It seems that Doctrine tries to save the Attachment
first, cannot find a value for the column attachment_linkassetuuid
, sets it to null
, and the foreign key constraint is broken.
How to define the entities correctly and get the cascade persisting working?
Asset
namespace MyDoctrineDataAccess\Model\Entity;
...
/**
* Asset
*
* @ORM\Table(name="tbl_asset")
* @ORM\Entity
*/
class Asset
{
/**
* @var string @ORM\Column(name="asset_uuid", type="string", length=36, nullable=false)
* @ORM\Id
*/
private $uuid;
/**
* @var \MyDoctrineDataAccess\Model\Entity\Attachment
* @ORM\OneToOne(targetEntity="MyDoctrineDataAccess\Model\Entity\Attachment", mappedBy="asset", cascade={"remove", "persist"}, orphanRemoval=true)
*/
private $attachment;
...
}
/**
* @param \MyDoctrineDataAccess\Model\Entity\Attachment $attachment
*/
public function setAttachment($attachment) {
$this->attachment = $attachment;
return $this;
}
/**
* @return the $attachment
*/
public function getAttachment() {
return $this->attachment;
}
Attachment
namespace MyDoctrineDataAccess\Model\Entity;
...
/**
* Attachment
*
* @ORM\Table(name="tbl_attachment", indexes={@ORM\Index(name="fk_attachment_uuid", columns={"attachment_linkassetuuid"})})
* @ORM\Entity
*/
class Attachment
{
/**
*
* @var string @ORM\Column(name="attachment_uuid", type="string", length=36, nullable=false)
* @ORM\Id
*/
private $uuid;
/**
*
* @var \MyDoctrineDataAccess\Model\Entity\Asset
* @ORM\OneToOne(targetEntity="\MyDoctrineDataAccess\Model\Entity\Asset", inversedBy="attachment", cascade={"persist"})
* @ORM\JoinColumn(name="attachment_linkassetuuid", referencedColumnName="asset_uuid")
*/
private $asset;
...
}
/**
*
* @param \MyDoctrineDataAccess\Model\Entity\Asset $asset
*/
public function setAsset($asset)
{
$this->asset = $asset;
return $this;
}
/**
*
* @return the $asset
*
*/
public function getAsset()
{
return $this->asset;
}
AssetService
namespace MyApi\V1\Rest\Asset;
...
class AssetService implements ServiceManagerAwareInterface
{
...
public function saveAssets($data)
{
$entityManager = $this->serviceManager->get('Doctrine\ORM\EntityManager');
$assetRepository = $entityManager->getRepository('My\Model\Entity\Asset');
$hydratorManager = $this->serviceManager->get('hydratormanager');
$hydrator = $hydratorManager->get('My\\Model\\Entity\\Hydrator\\EntityHydrator');
foreach ($data as $assetData) {
$asset = new Asset();
$hydrator->hydrate($assetData, $asset);
$entityManager->persist($asset);
$entityManager->flush();
}
}
...
}
Since @JoinColumn
defaults nullable
to true
according to the Doctrine documentation I don't really understand the error. But I do see that in your Attachment
entity @table
definition you declare an index:
indexes={@ORM\Index(name="fk_attachment_uuid", columns={"attachment_linkassetuuid"})}
Try once to remove this, rebuild your database and check if it solves your issue. If not then leave a comment and I will have another look.
Check the OneToOne
example in the Doctrine documentation. Adding an @index
like you do is not mentioned there. Doctrine will add the necessary indexes automatically to your relationship columns.
I think the problem might be that Asset
is not the owning side of the relationship. Check the documentation here. Try to change your setAttachment
method like this:
public function setAttachment($attachment)
{
$this->attachment = $attachment;
$attachment->setAsset($this);
return $this;
}