I want to restrict a delete action on my object, but it's not working.
My code from my first entity:
/**
* #ORM\ManyToMany(targetEntity="Season", inversedBy="clubs")
* #ORM\JoinTable(
* name="clubs_to_seasons",
* joinColumns={
* #ORM\JoinColumn(name="club_id", referencedColumnName="id", onDelete="cascade")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="season_id", referencedColumnName="id", onDelete="restrict")
* }
* )
**/
private $seasons;
And second:
/**
* #ORM\ManyToOne(targetEntity="League")
* #Assert\NotBlank(message="validation.custom.not_blank")
*/
private $league;
On database side everything is fine - I cannot delete a Season object, because it has a reference to Club object, but when I use a remove fuction from Entity Manager, Season object is deleted.
I know that on ORM side is a cascade={..} but I need a restrict, not cascade.
BUMP:
If I'm using one-to-many, many-to-one or one-to-one, everything is ok - when I try to delete an object (and I'm using onDelete="restrict" on the database side), then exceptions appears with message, that I cannot delete because I have other object connected with. But when I have many-to-many (as in my example), and I have a season associated with any club (and I have onDelete="restrict"), still I can delete a season using entity manager. But when I'm deleting season directly on the db side, message appears, and I cannot delete this.
What is wrong with many-to-many?
EDIT:
OK, now it's working.
My solution for the future:
I removed many-to-many relation from both entities. I have made a third entity - clubToSeason. Previously this entity was autogenerated, now it's not. And inside file of this third entity I have two many-to-one relations:
class ClubToSeason {
/**
* #ORM\ManyToOne(targetEntity="season", inversedBy="clubs")
**/
private $season;
/**
* #ORM\ManyToOne(targetEntity="club", inversedBy="seasons")
**/
private $club;
...
}
Related
Let's say I have two entities, Project and User with relation.
Project.php
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User")
* #ORM\JoinColumn(onDelete="SET NULL")
*/
private $creator;
When I remove the User entity, the doctrine leaves the User object(without ID) in the Project entity. In a normal situation, this is fine but I am using DomainEvents. In this scenario, after removing the User entity, DomainEvent triggers saving some data in the DB and secondary saving data(after removing) throw this error. This happens because of now in the Project entity we have the detached(from the EM) User object without ID.
I thought about a listener, that will remove empty objects in the entity after removing, but I am not sure that is a good variant
What is the best variant for solving this error?
The onDelete option doesn't apply a cascade removing.
If you want to do so I think you should have to add the cascade={"remove"} option to the ManyToOne.
Try as following :
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User", cascade={"remove"})
* #ORM\JoinColumn(onDelete="SET NULL")
*/
private $creator;
Removing entity in doctrine
I have a problem with my many to many relations
I have a User class that can be on multiple Teams
and a class Team that can have multiple Users
class User
/**
* #var Collection
* #ODM\ReferenceMany(
* targetDocument="App\Model\Document\Team",
* mappedBy="members",
* strategy="setArray"
* )
*/
protected $teams;
class Team
/**
* #var Collection|null
* #ODM\ReferenceMany(
* targetDocument="App\Model\Document\User",
* inversedBy="teams",
* strategy="setArray",
* sort={"username": "asc"},
* cascade={"persist"}
* )
*/
protected $members;
With these annotations, when I add members User to the team and I do a getMembers on an instance of Team, it works.
BUT, when I have an instance of a User (that's a member of a Team) the getTeams return nothing (empty PersistentCollection)
The reference is stored on the Teams Document, as an array of references
"members" : [
{
"$ref" : "User",
"$id" : ObjectId("XXX"),
"$db" : "readDat"
}
],
I don't understand, with the annotations as they are now, I thought Doctrine would do something like this db.getCollection('Team').find({"members.$id":ObjectId("XXX")})
to have the teams but it seems not.
On the other hand, I tried to inverse the mappedBy and inversedBy, I can't even getMembers (on a Team object) or getTeams (on a User object) anymore, both are empty Collection.
How can I have a good Many to Many (without duplicate the references in both Document) ?
We have a survey building application built in Symfony2 (think Survey Monkey or Google Forms). When a member of public accesses the survey, the various questions are built dynamically using Symfony's Form Builder and their answers are persisted using Doctrine. We currently collect an average of 1000 completed surveys a day without any trouble, but, every now and again, we get an Doctrine\DBAL exception.
Each answer to a question is persisted in a table which has a unique key consisting of the ID of the person filling in the survey and the ID of the question they are answering. Sometimes, when Doctrine tries to INSERT their answer, this key is violated and the query fails. As I mentioned, this happens fairly infrequently and we have been unable to replicate it on our test environment.
Things are made more complicated by the fact that all the Symfony Forms are build dynamically. Here is the code that actually does the persisting of the form data
public function save(\Symfony\Component\Form\Form $form, \Our\Namspace\Entity\Participant $participant)
{
/**
* $surveyReponse
*
* #var \Our\Namespace\Entity\SurveyResponse
*/
foreach ($form->getData() as $surveyResponseKey => $surveyResponse) {
$subQuestionId = $this->getQuestionIdFromSurveyResponseKey($surveyResponseKey);
$subQuestion = $this->getSubQuestionSettingsBySubQuestionId($subQuestionId);
if ($surveyResponse) {
$surveyResponse->setParticipant($participant)->setSubQuestion($subQuestion);
$participant->addResponse($surveyResponse);
$this->em->persist($surveyResponse);
}
$this->em->flush();
}
return true;
}
You can see that we encode the ID of the question (which is known as a SubQuestion in our domain) in the Form data in order to get the (sub)Question entity, then we set the Participant and the SubQuestion on the SurveyResponse object before persisting it. $this->em is just the Doctrine Entity Manager.
Without seeing all the code, it is probably difficult for anyone to figure out what is happening, but if anyone has had a similar problem in the past, maybe they could offer some advice.
We can and should wrap the persist and flush operations in a try/catch block and then handle the exception, but we'd really like to know why it is happening!
The relevant bits of the SurveyResponse entity look like
class SurveyResponse implements SurveyAwareInterface
{
/**
* id of the response.
*
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* the subQuestion to which the response refers.
*
* #var SurveySubQuestion
*
* #ORM\ManyToOne(targetEntity="\Our\Namspace\Entity\SurveySubQuestion", inversedBy="surveyResponses")
* #ORM\JoinColumn(name="sub_question_id", referencedColumnName="id")
*/
protected $subQuestion;
/**
* the participant.
*
* #var AbstractParticipant
*
* #ORM\ManyToOne(targetEntity="Our\Namespace\Entity\Participant", inversedBy="responses")
* #ORM\JoinColumn(name="participant_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $participant;
And there is this annotation in the Entity;
* #ORM\Table(name="survey_response",
* uniqueConstraints= #ORM\UniqueConstraint(
* name="participant_response", columns={"participant_id", "sub_question_id"})})
*
My purpose is to remove the record in the entity artist only if there are no other records of the entity connected soundtrack.
I tried with orphanRemoval in this way:
Soundtrack.php
/**
* #Assert\NotBlank(message = "soundtrack.artists.blank")
* #ORM\ManyToMany(targetEntity="Artist", inversedBy="soundtrack", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinTable(name="soundtrack_artist")
* #ORM\OrderBy({"name" = "ASC"})
**/
private $artists;
Artist.php
/**
* #ORM\ManyToMany(targetEntity="Soundtrack", mappedBy="artists")
*/
private $soundtrack;
but when I delete an entity record soundtrack, also clears the record of the entity artist even if it is linked to other records soundtrack (I think this is what you should expect from orphanRemoval).
Is there a way to remove that record an "orphan" only when no other records connected?
I also tried just like this:
**Soundtrack.php**
/**
* #Assert\NotBlank(message = "soundtrack.artists.blank")
* #ORM\ManyToMany(targetEntity="Artist", inversedBy="soundtrack", cascade={"persist"}, orphanRemoval=true)
* #ORM\JoinTable(name="soundtrack_artist")
* #ORM\OrderBy({"name" = "ASC"})
**/
private $artists;
but does not delete the records entity artist ..
orphanRemoval option explicitly thinks, that owning side object is the only instance that references its children. To make it works you should detach child from parent (unset reference) to make child deleted. With Many-2-many associations you should detach entities on both side (owned and inversed)
See Docs
When using the orphanRemoval=true option Doctrine makes the assumption
that the entities are privately owned and will NOT be reused by other
entities. If you neglect this assumption your entities will get
deleted by Doctrine even if you assigned the orphaned entity to
another one.
I'm new with Symfony2 and Doctrine 2 ORM, then i got a problem with composite FK association.
While the association OneToMany-ManyToOne by a single auto-increment ID works good, i got many troubles with the same kind of association but through a composite PK.
What i would like to do is an entity-structure that mirrors the below shema.
http://imageshack.us/photo/my-images/9/z07m.jpg (Sorry but I cannot insert images into the post)
where
prd_product_data.product_id
prd_product_data.language_id
make up together the PK of 'prd_product_data'
and
prd_product_image.pdoduct_id
prd_product_image.language_id
make up the FK linked to the table 'prd_product_data'.
These below
prd_product_image.pdoduct_id
prd_product_image.language_id
prd_product_image.file_image_id
make up, all together, the PK of 'prd_product_image'.
I read that Doctrine 2.1 and up, supports natively the composed PK - FK association but there are very few examples. Moreover, surfing on the web, i found just scattered fragments of similar situations but nothing of useful.
The main issue now, is that i'm unable to create one unique object for the two ids, like such an unique id.
For example...
Snapshot for the Entity ProductData where "product and language should make up the same object:
/**
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
protected $products_Pimgs;
/**
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="language")
*/
protected $products_Limgs;
Snapshot for the Entity ProductImage where *product_id* and *language_id* made up the FK for the entity ProductData:
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="ProductData", inversedBy="products_Pimgs")
* #ORM\JoinColumn(name="product_id", referencedColumnName="product_id")
*/
protected $product;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="ProductData", inversedBy="products_Limgs")
* #ORM\JoinColumn(name="language_id", referencedColumnName="language_id")
*/
protected $language;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="FileImage", inversedBy="files_images")
* #ORM\JoinColumn(name="file_image_id", referencedColumnName="id")
*/
protected $file_image;
From these snapshots it's evident that those keys are working separately.
In the end, this is my doctrine version, taken from the composer:
"doctrine/orm": ">=2.2.3,<2.4-dev",
How can i create an unique reference with two objects with ORM?
Read the documentation chapter Composite Primary Keys.
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
protected $products_Pimgs;
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="language")
*/
protected $products_Limgs;