Symfony2 and Doctrine2 - Set onDelete - php

I have two entities:
Manuscript and Tasks.
In the tasks table, I have the manuscript id and some extra data.
Also, in the tasks entity I have
/**
* #ORM\OneToOne(targetEntity="Manuscript")
* #ORM\JoinColumn(name="manuscript_id", referencedColumnName="id", onDelete="CASCADE")
**/
private $manuscript;
But I would like to delete the specific task when deleting the menuscript.
When trying to delete the manuscript, I am getting:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
IS it possible to do this with the onDelete, or should I delete the task manually?
Thank you.

Done by adding:
/**
* #ORM\OneToOne(targetEntity="Task", mappedBy="manuscript", cascade={"remove"})
*/
private $task;
In the manuscript entity.

Related

Cannot delete a records (OneToMany) with Symfony

I have 2 entities linked together PICTURE <-(OneToMany)-> NOTE (see class details below). When I tried to delete a picture record I got the following message from Symfony
An exception occurred while executing 'DELETE FROM Picture WHERE id =
?' with params [118]: SQLSTATE[23000]: Integrity constraint violation:
1451 Cannot delete or update a parent row: a foreign key constraint
fails (symfony.note, CONSTRAINT FK_6F8F552A8671F084 FOREIGN KEY
(picture_id) REFERENCES Picture (id))
I find it strange because if the note.author_id is the same as the current user, then I can delete the picture (and the note associated to the picture) without any problem.
here some details of my class picture and note:
Class Picture
{
/**
* #ORM\OneToMany(targetEntity="XXX\XXXBundle\Entity\Note", mappedBy="picture", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="note_id", referencedColumnName="picture_id", onDelete="CASCADE")
**/
private $notes;
}
Class Note
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="XXX\XXXBundle\Entity\Picture", inversedBy="notes")
**/
private $picture;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Sdz\UserBundle\Entity\User", cascade={"persist"})
*/
private $user;
}
Here my controller to delete the picture. FYI picture is a collection in my form. I set the option allow_delete to true
foreach($pictures as $picture) // $pictures is the initial list of picture
{
if(false === $data_form->getPictures()->contains($picture))
{
$em->remove($picture);
}
}
You have constraints on database that prevents you from cascaded deleting. I would suggest to use phpMyAdmin tool (mysql command line would be horrible to use for checking constraints): open both tables structure tab, go into relational view, and here check how constraints are set.
You may have different constraints set inside doctrine mappings and inside database, and it may work fine, until you try to perform an action on database, that collides with database constraints, like here.

doctrine 2 duplicate entity when add with foreign key

I have 2 tables in db : 'User' & 'Task'.
The task has a foreign key IdUser in cascade and this is the doctrine annotation on it :
/**
* #var \MyBundle\Entity\User
*
* #ORM\ManyToOne(targetEntity="\MyBundle\Entity\User", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idUser", referencedColumnName="id")
* })
*/
private $idUser;
My problem is when i try to create a new Task :
I set my task with my current user and then i persist & flush it. Everything goes fine exept that in database instead of linking this task to my current user, it duplicates my current user and link my Task to the new duplicated user.
Any idea how to avoid this ?

Doctrine's JoinColumns not working properly

I'm trying to make a ManyToOne association to work in doctrine, but no luck, here's the code of my relationship :
// the entity : Product
/**
* #Id
* #ManyToOne(targetEntity="ProductsModule\Entity\Configuration", inversedBy="product")
* #JoinColumns={#JoinColumn(name="id_type", referencedColumnName="id"),
* #JoinColumn(name="id_site", referencedColumnName="id")}
*/
private $configurations;
/**
* #Id
* #ManyToOne(targetEntity="ProductsModule\Entity\Picture", inversedBy="product")
* #JoinColumn(name="id_picture", referencedColumnName="id")
*/
private $picture;
and the inverse of the association is :
// the entity : Configuration
/**
* #OneToMany(targetEntity="ProductsModule\Entity\Product", mappedBy="configurations")
*/
private $product;
// the code in the controller
$product = new Product;
$product->setConfiguration($configuration); // the configuration object is retrieved from DB
$product->setPicture($picture);
$this->em->persist($product);
try
{
$this->em->flush();
}
catch (\Exception $e)
{
var_dump($e->getMessage());die();
}
The problem is that Doctrine tries to set the first column of JoinColumn (in the example above : id_type) but it ignores the second column, which throws the following error :
An exception occurred while executing 'INSERT INTO tableX (id_picture, id_type) VALUES (?, ?)' with params [1, 1]:SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`db`.`tableX`, CONSTRAINT `fk2` FOREIGN KEY (`id_site`) REFERENCES `sites` (`id`))
the product entity in itself is an entity that was born out of a ManyToMany relationship (that's why it has two primary keys), I just changed the names of the entities to keep the code private, because I'm not allowed to share it.
thank you.
It seems that you have with a foreign key related to site property try to update your schema with :
app/console doctrine:schema:update --force
If you got the same error try to drop the table or the database if this will not create any problem and make sure to export the sql file of the database and remove all foreign key , import your data then re-excute the commande :
app/console doctrine:schema:update --force

Symfony2 OneToMany bidirectional referencing not id column

I depends on an external api to populate my tables, and with this relationships i can handle some required functions on the app with less queries.
Instead of the errors and warnings the tables and FK are created after use the command, but i dont know if i can just bypass this errors or it will generate problems in the future.
Obviously i can just references the id and the problem will dissapear, but need to now if this is possible.
I have two tables:
RARITIES
id
name
...
ITEMS
id
item_rarity
...
And the entities looks like:
class Rarity
{
...
/**
* #ORM\OneToMany(targetEntity="Item", mappedBy="rarity")
*/
private $items;
public function __construct() {
$this->items = new ArrayCollection();
}
...
}
class Item
{
...
/**
* #ORM\ManyToOne(targetEntity="Rarity", inversedBy="items")
* #ORM\JoinColumn(name="item_rarity", referencedColumnName="name")
**/
private $rarity;
...
}
When i create or update the schema, it outputs some errors and warnings:
[Doctrine\ORM\Tools\ToolsException]
Schema-Tool failed with Error 'An exception occurred while executing 'ALTER TABLE items ADD CONSTRAINT FK_E11EE94D3139CB89 FOREIGN KEY (item_rarity) REFERENCES rarities (name)':
SQLSTATE[HY000]: General error: 1005 Can't create table 'd2a.#sql-4fa_7c' (errno: 150)' while executing DDL: ALTER TABLE items ADD CONSTRAINT FK_E11EE94D3139CB89 FOREIGN KEY (item_rarity) REFERENCES rarities (name)
[Doctrine\DBAL\DBALException]
An exception occurred while executing 'ALTER TABLE items ADD CONSTRAINT K_E11EE94D3139CB89 FOREIGN KEY (item_rarity) REFERENCES rarities (name)':
SQLSTATE[HY000]: General error: 1005 Can't create table 'd2a.#sql-4fa_7c' (errno: 150)
[PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'd2a.#sql-4fa_7c' (errno: 150
Thanks in advice!
I suspect this has something to do with trying to link the two via 'name', which Doctrine does not believe to be a unique Identifier. There could be two Rarities with the same name as far as Doctrine is concerned. The reason 'id' works is because it is declared as the Primary key in the annotation using #Id, and therefore assumed to be unique:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
Without looking into it, I would assume that this relationship requires that Items references back to a Primary key.
First of all, thanks to Alex, he gives me the idea of whats going on.
Like he said "There could be two Rarities with the same name as far as Doctrine is concerned" so, lets make rarities.name column as unique:
/**
* Rarity
*
* #ORM\Table(name="rarities",
* uniqueConstraints={#ORM\UniqueConstraint(name="unique_name", columns={"name"})})
* #ORM\Entity
*/
class Rarity
{
And it works, no errors, no warnings, column items.item_rarity referencing rarities.name, and rarities.name is not a primary key in the table.
I hope it helps others, it took me time!

Doctrine2 inheritance - 1452 : Integrity constraint violation

I deployed my projet on a new server and the error "SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails" shows up when i try to INSERT a class with inheritance :
/**
* #ORM\Table(name="prosante")
* #ORM\Entity
*/
class ProSante extends Base
{
/**
* #ORM\Column(type="string")
*/
protected $firstName;
}
/**
* #ORM\Table(name="base")
* #ORM\Entity(repositoryClass="Test\MyBundle\Entity\BaseRepository")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"base" = "Base",
* "prosante" = "ProSante",
* "pharmacie" = "Pharmacie"})
*/
abstract class Base
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
}
Log :
[2012-06-11 15:42:46] doctrine.DEBUG: INSERT INTO base (name) VALUES (?) ({"1":"Blabla"}) [] []
[2012-06-11 15:42:46] doctrine.DEBUG: INSERT INTO prosante (id, firstname) VALUES (?, ?) ({"1":"0","2":"PATRICK"}) [] []
I don't know what to do since the error doesn't show up when i do the same INSERT on localhost.
EDIT
I check "SELECT LAST_INSERT_ID();" after manualy insert a new "Base" into my database, its doesn't return 0, i don't understand.
SOLUTION It was a driver problem, i change it and it works.
It appears doctrine is interpreting "Base" as its own table. I think what you want to achieve here is to have your Base class as a mapped super class.
To do this simply annotate it as:
#MappedSuperclass
And then you can safely extend it into your other Entities..
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#mapped-superclasses
I experienced quite a similar problem and spent a lot of time searching for its cause, so I allow myself to share my solution here as this is the closest question I found on SO. Hope this may help some people :)
In my case
Doctrine was throwing the same foreign key constraint violation exception, although the auto-generated key in the first query (for base class) was successfully passed on to the second query (for subclass). Second query was still failing with this constraint violation and transaction was rolled back.
Digging into logs (I'm using MariaDB on CentOS), I found this error:
[ERROR] Transaction not registered for MariaDB 2PC, but transaction is active
My solution
It turned out my MariaDB service was improperly installed or updated (I don't know exactly, someone else did it).
Running mysql_upgrade solved my issue.

Categories