I'm new with symfony2, and I started a project of blog. This project has two entities, one of posts (Noticia) and one with comments (Comentario).
I need to delete a post but I can't because of the relationship with comments.
Here is my attribute:
/**
* #ORM\ManyToOne(targetEntity="Noticia", inversedBy="comentarios", onDelete="SET NULL")
* #ORM\JoinColumn(name="noticia_id", referencedColumnName="id")
*/
private $noticia;
/**
* #ORM\OneToMany(targetEntity="Comentario", mappedBy="noticia")
*/
private $comentarios = array();
I tried to put onDelete="SET NULL" but, when I updated my database with doctrine: php app/console doctrine:schema:update --force I got this error:
The annotation #ORM\ManyToOne declared on property Noticia
Bundle\Entity\Comentario\::$noticia does not have a property named "onDelete".
Avaible properties: targetEntity, cascade, fetch, inversedBy
I believe that the onDelete="SET NULL" should be part of the JoinColumn annotation, not the ManyToOne annotation.
One Way would be to search for all comments with the article relationship, you want to delete.
So first delete all the comments, than the article itself.
That a the eaysiest way without changing the annotation.
Related
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;
What values goes inside this inversedBy annotation as well as the mappedBy annotation? Also what is targetEntity and referencedColumnName?
Here is an example of my comment entity. As you can see, in my tutorials it says to write the string comments inside the inversedBy attribute and \Application\Entity\Post inside the targetREntity attribute.
/**
* This class represents a comment related to a blog post.
* #ORM\Entity
* #ORM\Table(name="comment")
*/
class Comment
{
/**
* #ORM\ManyToOne(targetEntity="\Application\Entity\Post", inversedBy="comments")
* #ORM\JoinColumn(name="post_id", referencedColumnName="id")
*/
protected $post;
}
For this one, it says comments. What exactly is this comments string referring to?
I dont know what comments means. Is this a mapping to a table, or the ORM name of the class at the top, or something else.
Also,
Here is an example of where mappedBy is used:
/**
* #ORM\Entity
* #ORM\Table(name="post")
*/
class Post
{
// Post status constants.
const STATUS_DRAFT = 1; // Draft.
const STATUS_PUBLISHED = 2; // Published.
/**
* #ORM\OneToMany(targetEntity="\Application\Entity\Comment", mappedBy="post")
* #ORM\JoinColumn(name="id", referencedColumnName="post_id")
*/
protected $comments;
I started reading about owning sides and inverse sides click here but it was extremely difficult to understand.
Any details on anything here would be great.
Any help would be great.
I'm not doctrine expect but I used to work with it for some time so I'll try to explain what I know so far.
InversedBy refers to $comments property (field) in Post entity and vice versa.
The inverse side has to use the mappedBy attribute of the OneToOne,
OneToMany, or ManyToMany mapping declaration. The mappedBy attribute
contains the name of the association-field on the owning side.
The owning side has to use the inversedBy attribute of the OneToOne,
ManyToOne, or ManyToMany mapping declaration. The inversedBy attribute
contains the name of the association-field on the inverse-side.
When you use #ORM\ManyToOne annotation you are creating n:1 relationship. There are three types of mapping:
bidirectional - Post with access to Comment and vice versa
unidirectional - Post with $comments field full of Comment entities but you won't have ability to access Post from Comment, because it is not mapped back
self-referencing - Category with with self-reference to parent Category which is entity of same type
TargetEntity tells to which entity you are creating relationship. Imagine foreign key. When you create foreign key you need to specify referencing table.
ReferencedColumnName tells to which column foreign key should be created.
Doctrine is not magic. It is just Object Relation Mapping. Think about it like when you used SQL to create relations. A lot of things are almost same.
I'm trying to map a Milestones to a Project but when I try to reference the relation it's always returning null.
The database looks perfect, the targetEntity paths are correct and the scheme is validating by using
doctrine:scheme:validate
project.php
/**
* #ORM\OneToMany(targetEntity="Planning\Readmodel\Project\Milestone\Milestone", mappedBy="project", cascade={"persist", "remove"})
*/
private $milestones;
milestone.php
/**
* #ORM\ManyToOne(targetEntity="Planning\Readmodel\Project\Project", inversedBy="milestones", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="projectId", referencedColumnName="projectId")
*/
private $project;
But when I try to get the milestone I get null using:
$this->milestones;
Any idea what I might be doing wrong? Thank you.
Your owning entity definition i.e Project looks fine to me but your inversed entity i.e Milestone has a problem in JoinColumn annotation in JoinColumn annotation name relates to the column of your current entity which hold the relation to project entity but in referencedColumnName you have to provide the column of your parent entity that is primary key of project entity which should be referencedColumnName="id"
So your annotation for milestone entity should be like
/**
* #ORM\ManyToOne(targetEntity="Planning\Readmodel\Project\Project", inversedBy="milestones", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
According to the official docs 5.11. Mapping Defaults
The name of the join table defaults to a combination of the simple,
unqualified class names of the participating classes, separated by an
underscore character. The names of the join columns default to the
simple, unqualified class name of the targeted class followed by
“_id”. The referencedColumnName always defaults to “id”, just as in
one-to-one or many-to-one mappings.
Make sure to update your database by running doctrine update command
[Using Symfony2 & Doctrine]
I have two classes
/* AppBundle\Entity\AccessToken
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User)
*/
protected $user;
and AppBundle\Entity\User, which contains no references to AppBundle\Entity\AccessToken. I get the famous parent conflict error from symfony attempting to delete a persisted User object.
Is there a way I can easily remove these access tokens, or set the user_id NULL without manually looping through my entities?
On a bidirectional association I can use cascade. I can't figure out what to do here.
Any thoughts?
You can set on delete parameter on your association.
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User)
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $user;
I'm trying make an entity with doctrine that has three associations with other entities
So an Item is associated with:
Must be associated with One Rssfeed, which it originates from
Can be associated with One or more Locations
Can be associated with one or more Tags
Here is my attempt:
class Item{
/**
* #ManyToOne(targetEntity="Rssfeed")
*/
protected $rssfeed;
/**
*
* #ManyToMany(targetEntity="Location")
*/
protected $locations;
/**
*
* #ManyToMany(targetEntity="Tag")
*/
protected $tags;
}
Now
If an Rssfeed is removed, associated items must be removed too
If an item is removed, Rssfeeds, and Locations, and Tags attached to that item should be detached
If a Location, or Tag is removed, the associated items should just be detached, because they are optional associations.
How should I change my code to accomplish that?
For each association in your Item entity, add onDelete="SET NULL" to the #JoinColumn annotation. Inside your location and tag entities, find the JoinColumn annotations and add onDelete="SET NULL" for the association with "Item". Under the RssFeed entity, find each #JoinColumn annotation and add onDelete="SET NULL".
Note that you can also use Doctrine cascade operations to achieve this (i.e. cascade={"remove"}, etc; however, it will likely be significantly slower as the operating is not performed at the RDBMS level.
U have to add #JoinColumn with onDelete="CASCADE" for $rssfeed and onDelete="SET NULL" for foreign keys in Location and Tag entities.
/**
* #ManyToOne(targetEntity="Rssfeed")
* #JoinColumn(name="rssfeed_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $rssfeed;