Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine - Multiple models referencing same id field in another model

Tags:

sql

php

doctrine

I have a Files Model, and Multiple (currently 3) different other Models (Article, Job, Event) that can all have files, that are stored in the Files Model.

The problem is that when i generate the tables via the CLI-Tool (./doctrine build-all-reload), i get this error message:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot 
add or update a child row: a foreign key constraint fails 
(`my_database/articles`, CONSTRAINT `articles_id_files_target_id`
FOREIGN KEY (`id`) REFERENCES `files` (`target_id`))

File is defined as (No relations are defined in this Model defined):

columns:
  id:
    primary: true
    autoincrement: true
    type: integer(4)
  target_id: integer(4)
  filename: string(255)
[...]

All 4 Models have this relation-definition:

  relations:
    Files:
      type: many
      class: File
      local: id
      foreign: target_id

This is the Php-Code that Doctrine generates (BaseFile.php):

public function setUp()
{
    parent::setUp();
    $this->hasOne('Publication', array(
         'local' => 'target_id',
         'foreign' => 'id'));

    $this->hasOne('Event', array(
         'local' => 'target_id',
         'foreign' => 'id'));

    $this->hasOne('Article', array(
         'local' => 'target_id',
         'foreign' => 'id'));

    $this->hasOne('Job', array(
         'local' => 'target_id',
         'foreign' => 'id'));
}

I understand why this happens (The Constraints can not be setup for multiple tables), but have no idea how i could solve this problem without mutltiple file tables or an association table.

Is there a way to tell Doctrine that it should not create the relations in the File model?

Any good ideas?

like image 962
smoove Avatar asked Jan 30 '26 10:01

smoove


1 Answers

You can use Doctrine Inheritance Mapping. Basically you need to create abstract file entity (model) and the concrete file entities (extended from abstract file entity) for each of article, job and event. Then each of Article, Job and Event should have one to many connection to ArticleFile, JobFile and EventFile respectively. Check code samples below:

<?php
use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({
 *     "article" = "ArticleFileEntity",
 *     "job" = "JobFileEntity",
 *     "event" = "EventFileEntity"
 * })
 * @ORM\Table(name="file")
 */
abstract class AbstractFile 
{
 private int $id;
}
<?php
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class ArticleFileEntity extends AbstractFileEntity 
{
}
<?php

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="customer")
 * @package Modules\Customer\Domain\Entities
 */
class ArticleEntity 
{
     /**
     * Article file collection
     *
     * @ORM\OneToMany(targetEntity="ArticleFileEntity", cascade={"persist","remove"}, orphanRemoval=true)
     * @var Collection
     */
    protected Collection $files;
}

REF: https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/inheritance-mapping.html

like image 156
v.orujov Avatar answered Feb 02 '26 03:02

v.orujov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!