ForeignKeyConstraintViolationException even with cascade remove - symfony

I'm trying to delete a OneToOne Entity relation.
A demand can only have one accepted purpose (proposition).
So, this is my demand entity:
class DemandeTransport extends AbstractEntity
{
/**
* #ORM\OneToOne(targetEntity=PropositionTransport::class, cascade={"remove"})
*/
private ?PropositionTransport $propositionAcceptee;
}
It's a unidirectional relationship.
So when I delete a demand, it would delete the propositionAccepte too; but I got this error:
There is a ForeignKeyConstraintViolationException for the Doctrine
entity associated with "DemandeTransport".
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(transporteur.demande_transport, CONSTRAINT FK_1387DBFBF9EDB3E8
FOREIGN KEY (proposition_acceptee_id) REFERENCES
proposition_transport (id))

Related

Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails - doctrine

My userland code:-
$projects = $this->doctrine->getRepository(Project::class)->findBy(['deletionDate' => new DateTime('today + 364 day')]);
foreach($projects as $project){
$project = $this->entityManager->find('App\Entity\Project', $project->getId());
$this->entityManager->remove($project);
}
$this->entityManager->flush();
Here's the error:
An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`foo`.`entry`, CONSTRAINT `FK_2B219D70166D1F9C` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`))
and here's what I'm attempting:-
class Entry
{
/**
* #ORM\ManyToOne(targetEntity=Project::class, inversedBy="entries")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id", onDelete="CASCADE")
*
* #Assert\NotBlank
*/
public ?Project $project;
}
class Project
{
/**
* #ORM\OneToMany(targetEntity="Entry", mappedBy="project", cascade={"remove"})
*/
public Collection $entries;
}
This has nothing to do with Doctrine itself but with the general database rule - you cannot delete rows that other rows in the database depend on.
Now, something that caught my eye was:
#ORM\JoinColumn(name="project_id", referencedColumnName="id", onDelete="CASCADE")
Namely, you have onDelete="CASCADE", however:
`FK_2B219D70166D1F9C` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`))
tells us a whole different story.
It seems that your database and your model are not in sync. Do you manage that by migrations? If so, did you run all of them?
You could try to:
php bin/console doctrine:migrations:diff
which will generate a single migration containing all the differences.
Be careful, inspect detected changes and apply them after making any necessary adjustments.
Update:
Given that you do not manage DB changes via migrations of any sort, the only way would be to execute the ALTER query by hand in order to fix this issue.
Something like this:
ALTER TABLE entry DROP FOREIGN KEY FK_2B219D70166D1F9C;
ALTER TABLE entry ADD FOREIGN KEY FK_2B219D70166D1F9C(project_id)
REFERENCES project(id) ON DELETE CASCADE;

Self referencing addReference getReference in the same fixture

I have a simple question about Fixtures in Symfony and Doctrine.
I have an Entity "Project" and I would like to self-referencing this project. For example I tried this :
$project1 = new Question();
$this->addReference("initiatives", $project1); //referencing
$project1->setItem('Project Initiatives');
$project1->setInverse(false);
$project1->setProjectHead($this->getReference("initiatives")); // get the reference of himself
$manager->persist($project1);
My entity (extract) :
/**
* #ORM\ManyToOne(targetEntity=Project::class, inversedBy="projects")
*/
private $project_head;
/**
* #ORM\OneToMany(targetEntity=Project::class, mappedBy="project_head")
*/
private $projects;
public function setProjectHead(?self $project_head): self
{
$this->project_head = $project_head;
return $this;
}
But It does not work. I have this error :
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
I have just ONE line in my db.
I think he can't UDPATE because when I try to add others fixtures, the message appears. But I don't know how to fix this.
Thanks a lot for helping

On delete of Parent entities - null the association on the other entity

I am trying to solve my issue on Doctrine ORM. I have 2 parent entities: CompanyDoctrineEntity and ServiceDoctrineEntity and 1 entity that are associated with these 2 (but the association is not required) OrderLinkRedirectLogDoctrineEntity. The association in OrderLinkRedirectLogDoctrineEntity is defined by:
class OrderLinkRedirectLogDoctrineEntity {
/**
* #Id
* #Column(type="integer")
* #ORM\GeneratedValue()
*
* #var int $id
*/
private $id;
/**
* Many logs have one company. This is the owning side.
*
* #ManyToOne(targetEntity="CompanyDoctrineEntity", cascade="detach")
* #JoinColumn(name="company_id", referencedColumnName="id")
*
* #var CompanyDoctrineEntity $company
*/
private $company;
/**
* Many logs have one service. This is the owning side.
*
* #ManyToOne(targetEntity="ServiceDoctrineEntity", cascade="detach")
* #JoinColumn(name="service_id", referencedColumnName="id")
*
* #var ServiceDoctrineEntity $service
*/
private $service;
}
My expected behaviour is, whenever either CompanyDoctrineEntity or ServiceDoctrineEntity is removed from the database, the association in the OrderLinkRedirectLogDoctrineEntity will be NULLed, which I believe what the cascade="detach" does, but for some reason, it's not working, as I am getting the following errors:
Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test_app2`.`logs_order_link_redirects`, CONSTRAINT `FK_6C1CA74CED5CA9E6` FOREIGN KEY (`service_id`) REFERENCES `app_services` (`id`)) in /Users/arvil/Projects/app2.test/public_html/wp-content/themes/app-theme/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:117
Stack trace:
#0 /Users/arvil/Projects/app2.test/public_html/wp-content/themes/app-theme/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php(117): PDOStatement->execute(NULL)
#1 /Users/arvil/Projects/app2.test/public_html/wp-content/themes/app-theme/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(1054): Doctrine\DBAL\Driver\PDOStatement->execute()
#2 /Users/arvil/Projects/app2.test/public_html/wp-content/themes/app-theme/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(656): Doctrine\DBAL\Connection->exe in /Users/arvil/Projects/app2.test/public_html/wp-content/themes/app-theme/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php on line 49
I'm far from an expert on Doctrine, so take this with a grain of salt and test thoroughly.
Your relations are not nullable (defaults to false), which is why your foreign key constraint is complaining: logs_order_link_redirects.service_id (and company_id) isn't allowed to be null. That likely wasn't a problem before because you're not inserting the OrderLinkRedirectLogDoctrineEntity entities without the relationships. If you were to say
$redirectLog = new OrderLinkRedirectLogDoctrineEntity();
$entityManager->persist($redirectLog);
$entityManager->flush();
you'd probably trigger the same error immediately.
Also, I don't believe you want cascade={"detach"} here. Detach would just remove the entity from this entity manager instance (in other words: for the running process), so anything you'd do to the entity after detaching it wouldn't be reflected in the database when $entityManager->flush() is called. On the next request, the entity would be back in the entity manager.
I believe that adding nullable=true to your ManyToOne's JoinColumn annotations, e.g.
#JoinColumn(name="company_id", referencedColumnName="id", nullable=true)
will get you the result you're looking for. You'll need to update your database schema afterwards for changes to be applied to the tables. Also, make sure you don't have (or add) orphanRemoval=true on the inverse side so Doctrine doesn't automatically remove your entities if they lose their parent.
I prefer adding the JoinColumn annotation to relationships as well, even though it's not required if you're fine with Doctrine's default field name choices. Adding nullable=false makes it more explicit that this relationship cannot be null. That's implied if you don't have nullable=true, but when I start looking at relationships and need to know whether they can be null or not, I'm usually confused by something and I don't have mental energy to spare to actively remember the default values for important attributes.

One to One mapping on the same entity remove issue Symfony

I have an entity Product that can be linked to another product of the same type ( So one to one mapping from Product to Product ).
The problem occurs when I'm trying to remove the product from the database because it has a foreign key.
An exception occurred while executing 'DELETE FROM product WHERE id = ?' with params ["25"]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (acme.product, CONSTRAINT FK_BAD80AF68031A592 FOREIGN KEY (linked_to_id) REFERENCES product (id))
This is how I defined the relationship
/**
* #ORM\OneToOne(targetEntity="App\Entity\Product", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="linked_to_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $linkedTo;
Any ideas what to set on the relationship to avoid this FK removal issue?

Symfony 4 how to delete entity from OneToMany relationship

I'm having a bit of a problem deleting an entity assigned to another with a OneToMany relationship.
I have an entity called Business and it has a property "units" which is a collection of Unit entities on a OneToMany relationship (business can have many units).
When i try to delete a single unit from the database i get a violation of the foreign keys, it won't let me remove the unit from the business entity.
Here is a condensed version of both entities:
BUSINESS
/**
* #ORM\Entity(repositoryClass="App\Repository\BusinessRepository")
*/
class Business
{
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="App\Entity\Unit", mappedBy="business")
*/
private $units;
}
UNIT
/**
* #ORM\Entity(repositoryClass="App\Repository\UnitRepository")
*/
class Unit
{
/**
* #var Business
* #ORM\ManyToOne(targetEntity="App\Entity\Business", inversedBy="units")
* #ORM\JoinColumn(name="business_id", referencedColumnName="id")
*/
private $business;
}
So in the UnitRepository i have a delete method:
/**
* #param Unit $unit
*/
public function delete(Unit $unit){
$this->em->remove($unit);
$this->em->flush();
}
And i get this error:
An exception occurred while executing 'DELETE FROM unit WHERE id = ?' with params [1]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`businessdirectory`.`unit_day`, CONSTRAINT `FK_F03D80CEF8BD700D` FOREIGN KEY (`unit_id`) REFERENCES `unit` (`id`))
I don't know if i have set up the relationship incorrectly or not here, but i should be able to delete a single unit from a business, and i should be able to delete the entire business with it's units.
See if a Unit entity is the owning side of another relationship. At that point you would need to delete all the entities that depend on Unit first. You can freely delete the owned side of a One-To-Many relationship but you would need to clear all owned elements before deleting the owning side.

Resources