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
Related
I am connecting my entity "data" with my entity "documents"
/**
* #ORM\ManyToOne(targetEntity="Documents")
* #ORM\JoinColumn(name="document", referencedColumnName="id")
*/
private $document;
If the data is not connected to any document, then my database shows NULL.
But I want it to be empty, when it is not connected. This is my approach:
/**
* #ORM\ManyToOne(targetEntity="Documents")
* #ORM\JoinColumn(name="document", referencedColumnName="id", nullable=false)
*/
private $document;
But I get an error message:
Migration 20190405143905 failed during Execution. Error An exception
occurred while executing 'ALTER TABLE data CHANGE document document
INT NOT NULL':
An exception occurred while executing 'ALTER TABLE data CHANGE
document document INT NOT NULL':
SQLSTATE[HY000]: General error: 1832 Cannot change column
'document': used in a foreign key constraint 'FK_ADF3F363D8698A76'
You need to remove the document(s) entries linked to your data, otherwise you are breaking the foreign key constraint. Then you can set the document ID to null inside the data occurrence
If you can't delete the documents entries because you need them, then I recommend you migrate them to a temporary table, do the required changes on your database model, and then put the documents entries back into the original table
Context
I'm using Doctrine version 2.5.0 and I have two entities: Group and Item. I'm trying to create an unique constraint so that Items cannot have the same position in a Group:
/**
* #Entity
* #Table(uniqueConstraints={
* #UniqueConstraint(name="position", columns={"group_id", "position"})
* )
*/
class Item {
...
}
This works well.
Problem
I added an active field to the Item entity, so instead of deleting an Item, I 'inactivate' it. But now the unique constraint doesn't work anymore, since the Item stays in the database with his Group reference and his position.
Attempts
Looking at the Doctrine docs, I've discovered that I can use the options property with a where clause in the #UniqueConstraint:
/**
* #Entity
* #Table(uniqueConstraints={
* #UniqueConstraint(name="position", columns={"group_id", "position"},
* options={"where":"(active = 1)"})}
* )
*/
class Item {
...
}
But the I get the same error as before:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
'1-1' for key 'position'
Here is my deletion code:
$item->setActive(false);
$this->_em->persist($item);
$this->_em->flush();
foreach ($item->getNextItems() as $nextItem) {
$nextItem->setPosition($nextItem->getPosition() - 1);
$this->_em->persist($nextItem);
}
$this->_em->flush();
Any idea why the options property is not working?
Update
I realised a strange behaviour. Every time I run the command ./doctrine orm:schema-tool:update --force it recreates the index:
DROP INDEX position ON Item;
CREATE UNIQUE INDEX position ON Item (group_id, position);
But once I remove the options property and run the command, I get:
Nothing to update - your database is already in sync with the current
entity metadata.
It seems I read over this from the Doctrine docs:
SQL WHERE condition to be used for partial indexes. It will only have effect on supported platforms.
After research:
MySQL does not support partial indexes of this nature
My solution is to check if the Item is really unique in a LifeCycleEvent inside the entity:
/**
* #PostPersist #PostUpdate
*/
public function checkUnicity(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
$em = $eventArgs->getEntityManager();
// checking unicity here
// throw exception if not
}
if you have data already in database and then after you are adding unique constraint first please check in database that you have unique values or not.
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.
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!
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.