Merge is creating not working for children #OneToMany
I am using Php Doctrine and I am using #OnToMany mapping with cascade all. I have a parent class SalesOrder and child class SalesOrderDetails.
Case 1 : Save - When I save new record sales order along with sales order details. It is working as expected.
Case 2 : Update - Here is the issue, I am merging the Sales Order which is fine however its inserting new records for its children SalesOrderDetail instead of updating it. Ideally it should it apply mergebut for children as well but its not.
As of now, I am getting the Sales Order Details by id from DB then change the properties of it. Ideally that should not be the case, mean if we set the id to unmanned object, it should update instead of creating new records.
Note:
1. Merge is working with parent object if it has the id value.
2. I am not adding new item here, I am just updating the existing recorded through merge.
SalesOrder.php
/**
* #Entity #Table(name="sales_orders")
* */
class SalesOrder extends BaseEntity {
/**
* #OneToMany(targetEntity="SalesOrderDetail",cascade="all", mappedBy="salesOrder" )
*/
protected $itemSet;
function __construct() {
$this->itemSet = new ArrayCollection();
}
}
SalesOrderDetail.php
/**
* #Entity #Table(name="sales_order_details")
* */
class SalesOrderDetail extends BaseEntity {
/** #Id #Column(type="integer") #GeneratedValue * */
protected $id;
/**
* #ManyToOne(targetEntity="SalesOrder")
* #JoinColumn(name="order_no", referencedColumnName="order_no")
*/
protected $salesOrder;
}
Debug Mode screen
If I use cascade={"merge"}
I am getting different error if I am using Cascades merge
Type: Doctrine\ORM\ORMInvalidArgumentException Message: Multiple
non-persisted new entities were found through the given association
graph: * A new entity was found through the relationship
'Ziletech\Database\Entity\SalesOrder#itemSet' that was not configured
to cascade persist operations for entity:
Ziletech\Database\Entity\SalesOrderDetail#0000000052218380000000007058b4a6.
To solve this issue: Either explicitly call EntityManager#persist() on
this unknown entity or configure cascade persist this association in
the mapping for example #ManyToOne(..,cascade={"persist"}). If you
cannot find out which entity causes the problem implement
'Ziletech\Database\Entity\SalesOrderDetail#__toString()' to get a
clue. * A new entity was found through the relationship
'Ziletech\Database\Entity\SalesOrder#itemSet' that was not configured
to cascade persist operations for entity:
Ziletech\Database\Entity\SalesOrderDetail#0000000052218071000000007058b4a6.
To solve this issue: Either explicitly call EntityManager#persist() on
this unknown entity or configure cascade persist this association in
the mapping for example #ManyToOne(..,cascade={"persist"}). If you
cannot find out which entity causes the problem implement
'Ziletech\Database\Entity\SalesOrderDetail#__toString()' to get a
clue.
You have a mistake in your mapping, cascade needs an array
/**
* #OneToMany(targetEntity="SalesOrderDetail", cascade={"all"}, mappedBy="salesOrder" )
*/
protected $itemSet;
Related
I'm currently building Entity model and one of my Doctrine Entities have ManyToMany relation with an external dictionary (like ENUM). So the entity field will be an Array of Enum.
I'm looking for a way to have it as an array field on my entity, but to store it as a separate DB table.
Would like to get any advice/links/etc.
The question is a bit out of context but..
A many to many is already an array (Iterator) in your entity.
You can create your own entity acting as a Many To Many and set the column as enum.
Finally, I've decided to create an Entity to store this relation. To make sure it will be deleted on unlinking from the parent entity, I've used the orphanRemoval=true option on the OneToMany relation side.
class Entity {
/**
* #ORM\OneToMany(targetEntity="EntityType", mappedBy="entity", orphanRemoval=true)
*/
protected $types;
}
class EntityType {
/**
* #ORM\ManyToOne(targetEntity="Entity")
*/
protected $entity;
/**
* #ORM\Column(type="MyEnum")
*/
protected MyEnum $type;
}
I am migrating an old PHP project to Symfony. I am trying to create the entities based on the existing database schema which I can not change. I am facing a problem :
There is a table that would represent two different entities. Basically, there is a boolean (a tinyint(1)), if the boolean is false, then the row of the table is representing a cart. If the boolean is true, then the row is representing an order.
Is it possible for Doctrine to make the distinction between these and to fetch those entities accordingly ? The solution I was willing to implement was creating several entities and overwrite the find() and findAll() methods in these entities' repositories. Is there another way to achieve that ?
This is what doctrine call Inheritance Mapping.
So you'll have one Cart entity and one Order entity extended it.
/**
* #ORM\Table()
* #ORM\Entity(repositoryClass="App\Repository\CartRepository")
* #ORM\InheritanceType(value="SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="is_order", columnDefinition="BOOL DEFAULT FALSE")
* #ORM\DiscriminatorMap(
* value={
* CART::IS_CART=Cart::class,
* CART::IS_ORDER=Order::class
* }
* )
*/
class Cart {
const IS_CART = FALSE;
const IS_ORDER = TRUE;
... // Entity field, getters, setters, functions...
}
Then your Order Entity.
/**
* #ORM\Entity(repositoryClass=OrderRepository::class)
*/
class Order extends Cart {...}
There is maybe some mistake in this code I didn't test it but it should be ok.
I am getting the following json data from the client. JSON contains the parent and child details as below -
{
id : 1,
name : "Parent"
children : [
{ id : 1, name : "A" },
{ id : 2, name : "B" }
]
}
I am mapping these json data to Parent and Child Object.
Parent
class Parent{
/** #Id #Column(type="integer",name="order_no") #GeneratedValue * */
protected $id;
/**
* #OneToMany(targetEntity="Child",cascade={"merge"}, mappedBy="parent" )
*/
protected $children;
}
Child
class SalesOrderDetail extends BaseEntity {
/** #Id #Column(type="integer") #GeneratedValue * */
protected $id;
/**
* #ManyToOne(targetEntity="parent")
* #JoinColumn(name="parent_id")
*/
protected $salesOrder;
}
So far so good.
Now the issue is when I am trying to merge the parent
$em->merge($parent)
I am getting the following error. Note : The entire object parent and children are unmanaged object so I am trying to merge. If I just merge parent it works find but getting error if I am trying to save entire content of parent and its children.
Type: Doctrine\ORM\ORMInvalidArgumentException Message: Multiple
non-persisted new entities were found through the given association
graph: * A new entity was found through the relationship
'Ziletech\Database\Entity\Parent#itemSet' that was not configured to
cascade persist operations for entity:
Ziletech\Database\Entity\Child#0000000052218380000000007058b4a6. To
solve this issue: Either explicitly call EntityManager#persist() on
this unknown entity or configure cascade persist this association in
the mapping for example #ManyToOne(..,cascade={"persist"}). If you
cannot find out which entity causes the problem implement
'Ziletech\Database\Entity\Child#__toString()' to get a clue. * A new
entity was found through the relationship
'Ziletech\Database\Entity\Parent#itemSet' that was not configured to
cascade persist operations for entity:
Ziletech\Database\Entity\Child#0000000052218071000000007058b4a6. To
solve this issue: Either explicitly call EntityManager#persist() on
this unknown entity or configure cascade persist this association in
the mapping for example #ManyToOne(..,cascade={"persist"}). If you
cannot find out which entity causes the problem implement
'Ziletech\Database\Entity\Child#__toString()' to get a clue.
I'm very new using Doctrine, is the first project I work with it and I'm having an error while I try to insert a new user.
The thing is I've got a class User with a foreign key Country and when I try to insert a user Doctrine also try to insert the country, the country already exists so PDO launch an integrity constraint violation and Doctrine a Doctrine\DBAL\DBALException.
I know the annotation cascade={"persist"} makes the country entity to be written in the db, without it, doctrine launch another error:
A new entity was found through the relationship 'User#country' that was not configured to cascade persist operations for entity: Country#0000000078b1861f00007f935266d9fe. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Country#__toString()' to get a clue.
I've tried with all cascade options and only with persist and all the error above doesn't come up...
Is there something like cascade={"no-persist"} or something that tells doctrine the value of this attribute must be already inserted in table country???
Some code:
/**
* User
*
* #Table(name="user")
* #Entity
*/
class User {
...
/**
* #var Country
*
* #OneToOne(targetEntity="Country", cascade={"persist"})
* #JoinColumn(name="country", referencedColumnName="id")
*/
private $country
...
}
/**
* Country
*
* #Table(name="country")
* #Entity
*/
class Country {
...
/**
* #var integer
*
* #Column(name="id", type="integer")
* #Id
*/
private $id;
}
Any clue will be highly appreciated.
Thanks.
Put the cascade=persist back in.
You need to check the database to see if the country exists. Your insert with an existing country fails because the country object needs to be managed by the entity manager.
$country = $countryRepository->find($countryId);
if (!$country)
{
$country = new Country();
$entityManager->persist($country);
}
$user->setCountry($country);
I have an entity Template and another one Request. Essentially, a template represents an html form, and a request will represent a collection of values which the form was filled with and a reference to the template id.
class Request {
/**
* #Id #Column(type="integer")
* #GeneratedValue
*/
private $id;
/**
* #ManyToOne(targetEntity="Template", cascade={"persist"})
* #JoinColumn(name="templateId", referencedColumnName="id", nullable=false)
*/
private $template;
...
What I am trying to achieve is that when Request is loaded from the DB then the object comes holding the relevant Template object with all its data. However, when requests are saved there is no need to save the template too... thus cascade={"persist"} should not be there.
1- Load all templates from db
2- User selects a template from a dropdown
3- Tmeplate shows on screen and the user fills it in
4- Request is saved
$request = new \entities\Request();
//template already exist in the db
$template = $this->templateRepository->fetchTemplate(1);
$request->template = $template;
...
$this->entityManager->persist($request);
$this->entityManager->flush();
Now the problem is when I use casade persist it saves another Template in the templates table. If I do not use cascade persist it errors:
Fatal error: Uncaught exception 'Doctrine\ORM\ORMInvalidArgumentException' with message 'A new entity was found through the relationship 'entities\Request#template' that was not configured to cascade persist operations for entity: entities\Template#00000000343e07770000000073e3b0ec. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'entities\Template#__toString()' to get a clue.' in C:\Development\wamp\www\vendor\doctrine\orm\lib\Doctrine\ORM\ORMInvalidArgumentException.php on line 59
What is the correct Doctrine relationship setting to achieve the desired behaviour?