原则 - 多个模型在另一个模型中引用相同的 id 字段

Doctrine - Multiple models referencing same id field in another model

提问人:smoove 提问时间:5/19/2010 更新时间:2/15/2023 访问量:1414

问:

我有一个文件模型,以及多个(目前是 3 个)不同的其他模型(文章、作业、事件),它们都可以有存储在文件模型中的文件。

问题是,当我通过CLI工具(./doctrine build-all-reload)生成表时,我收到以下错误消息:

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`))

文件定义为(此模型中未定义任何关系):

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

所有 4 个模型都有以下关系定义:

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

这是 Doctrine 生成的 PHP 代码(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'));
}

我理解为什么会发生这种情况(无法为多个表设置约束),但不知道如何在没有多个文件表或关联表的情况下解决这个问题。

有没有办法告诉 Doctrine 它不应该在文件模型中创建关系?

有什么好主意吗?

PHP SQL 学说

评论

1赞 wimvds 5/19/2010
请问你为什么不使用关联表来解决它?这是一个非常灵活和高效的解决方案,因为它允许您将同一文件链接到不同的内容类型,而无需多次上传。以您当前的模型,这是不可能的......
0赞 smoove 5/20/2010
我真的可以用一个关联表解决这个问题吗?我如何让 Doctrine 知道“类型”字段?
0赞 Kevin Peno 3/5/2011
我不知道如何用教义来实现这一点,但问题可能在于教义在创建另一个表之前添加了一个依赖于另一个表的表。
0赞 Shane Stillwell 3/16/2011
Doctrine 需要在 Files 和其他模型中创建关系,以便知道表之间的关系。尝试在文件模型中定义关系并使用该指令。doctrine-project.org/documentation/manual/1_2/en/......owningSide: true
0赞 Peter Lindqvist 4/20/2011
我对你在这里想做什么感到困惑。所有其他模型是否都有一个或多个相关文件还是什么?

答:

0赞 Jayanath 4/20/2011 #1

如果需要,请尝试,
关系:

Files:
  type: many
  class: File
  local: target_id
  foreign: id
Files2:
  type: many
  class: File
  local: id
  foreign: id
0赞 Viktoras 5/2/2011 #2

您可以尝试以下操作:

columns:
    id: { type: integer(4), notnull: true, primary: true, autoincrement: true }
    target_id:  { type: integer(4), notnull: true }
    model:       { type: string, notnull: true }

文件模型需要知道链接条目的 id 和模型。因此,在“文件”中.class.php您还可以指定:

public function getArticles() {
    if (strcmp($this->getModel(), 'Articles')) {
        return Doctrine::getTable('Articles')->findOneById($this->getTargetId());
    } else {
        return false;
    }
}

可能有更好的方法,但在这种情况下,你有 1 个表,你不需要更多的关系,但你必须自己指定 getter/setter。因此,这取决于您的目标是否会成功。

0赞 v.orujov 2/15/2023 #3

您可以使用 Doctrine Inheritance Mapping。基本上,您需要为每个文章、作业和事件创建抽象文件实体(模型)和具体文件实体(从抽象文件实体扩展而来)。然后,Article、Job 和 Event 中的每一个都应该分别与 ArticleFile、JobFile 和 EventFile 建立一对多连接。查看下面的代码示例:

<?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;
}

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