I have an entity called PrintJob, with a ProductId field (amongst others). When I create a new instance of this entity and set all of the fields, then use persist followed by flush, I get an error saying that ProductId cannot be null.
I did a var_dump() on the $productId variable and it comes out as 47. I also did a var_dump() on getProductId() on the new entity (before persist/flush) and the value is still 47.
I think the problem lies with the relationship between the PrintJob entity and the Product entity. Here's the relationship from the PrintJob entity:
/**
* @OneToOne(targetEntity="Product")
* @JoinColumn(name="ProductId", referencedColumnName="ProductId")
*/
private $product;
I read somewhere that in the constructor, you need to set the relationship to an empty collection when you're creating new entities (rather than loading existing ones). Here is what I tried doing:
public function __construct()
{
$this->product = new \Doctrine\Common\Collections\ArrayCollection();
}
However, I get an error:
A new entity was found through a relationship that was not configured to cascade persist operations: Doctrine\Common\Collections\ArrayCollection@000000002cb4568d00000000e92b0fce. Explicitly persist the new entity or configure cascading persist operations on the relationship.
Any help would be much appreciated. The only alternative I've found is to not use relationships :(
I'm using Doctrine 2.0.7.
Additional info:
I'm not creating a new Product entity; the new PrintJob is being linked via the ProductId.
Here's how I am creating the entity - there are a lot of other fields that I can include in the code if it's useful, but I imagine they won't be as the issue is only occurring with ProductId...
// convert this quote to a print job
$printJob = new \Dpp\Model\PrintJob;
$printJob->setProductId($productId);
// ... other fields ...
\Dpp\System\Core::getEm()->persist($printJob);
\Dpp\System\Core::getEm()->flush();
\Dpp\System\Core::getEm() returns the EntityManager.
The mapping part from PrintJob to Product:
/**
* @OneToOne(targetEntity="Product", cascade={"persist"})
* @JoinColumn(name="ProductId", referencedColumnName="ProductId")
*/
private $product;
There is no equivalent mapping from Product to PrintJob.
Product entity - columns only:
namespace Dpp\Model;
/**
* @Entity
* @Table(name="Brd_Products")
*/
class Product
{
/**
* @Id @Column(type="integer", name="ProductId")
* @GeneratedValue
*/
private $productId;
}
Additional info #2:
@JohnM2 pointed out that my associations are not set up correctly. So, here's what I now have.
\Dpp\Model\PrintJob
/**
* @OneToOne(targetEntity="Product", cascade={"persist"})
* @JoinColumn(name="ProductId", referencedColumnName="ProductId")
*/
private $product;
/**
* @return \Dpp\Model\Product
*/
public function getProduct()
{
return $this->product;
}
/**
* @param \Dpp\Model\Product $product
* @return void
*/
public function setProduct($product)
{
$this->product = $product;
}
\Dpp\Model\Product
/**
* @Id @Column(type="integer", name="ProductId")
* @GeneratedValue
*/
private $productId;
public function getProductId()
{
return $this->productId;
}
The code that saves the new entity:
$productEntity = \Dpp\Query\Product::getById($productId);
$printJob = new \Dpp\Model\PrintJob;
$printJob->setProduct($productEntity);
\Dpp\System\Core::getEm()->persist($printJob);
\Dpp\System\Core::getEm()->flush();
The first line returns an instance of \Dpp\Model\Product. I checked that $productId is set and that $productEntity is populated correctly.
Unfortunately, I now get an error on the "persist" line:
Property productId does not exist
I have a relationship from PrintJob pointing to Product. Do I need one in the opposite direction?
Nearly there though, I hope!
Edit
Never mind, found this last one myself. I needed to set the join column name to productId not ProductId. Fixed. Thank you all :)
As far as I understand now, you have PrintJob::$product field and also PrintJob::$productId field.
And you are trying to establish a connection between PrintJob and Product using explicit productId "foreign key" field of the PrintJob entity.
But it's not how ORM works. You don't need PrintJob::$productId, Doctrine will create appropriate foreign column from PrintJob::$product field (that what's @JoinColumn annotation says: @JoinColumn(name="ProductId", referencedColumnName="ProductId")). So instead you should establish an association between PrintJob and Product by assigning Product entity (loaded by EntityManager) to PrintJob::$product field by PrintJob->setProduct($product).
Try adding cascade={"persist"} to the @OneToOne annotation of $product, like so:
/**
* @OneToOne(targetEntity="Product", cascade={"persist"})
* @JoinColumn(name="ProductId", referencedColumnName="ProductId")
*/
private $product;
By default Doctrine doesn't implicitly persists associations to other entities, have a look at this
Also remove this line $this->product = new \Doctrine\Common\Collections\ArrayCollection();
, it doesn't make sense to initialize something that is not a collection as a collection.
Hope it helps
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