【问题标题】:Symfony2/Doctrine: how to add more of the same entity in the same collection?Symfony2/Doctrine:如何在同一个集合中添加更多相同的实体?
【发布时间】:2015-11-02 08:18:27
【问题描述】:

我正在设计一个 Symfony2 应用程序,其中计算机实体与多个硬件组件相关联,即主板、CPU、磁盘、内存模块等。它们都由 Doctrine 中的实体表示。

我需要做的是将多个磁盘与同一台计算机关联,以防它的硬件配置中有多个相同的磁盘。我想避免Disk1、Disk2等多个字段,所以我在两个实体之间设置了ManyToMany关系:

实体计算机

//... 

/**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Components\Disk", inversedBy="computers")
 * @ORM\JoinTable(name="computers_disks")
 */
protected $disks;

实体磁盘

//...
enter code here
/**
 * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Computers\Computer", mappedBy="disks")
 */
protected $computers;

例如,我在我的 Fixtures 中运行此代码:

$testComputer = new Computer();
$cpu = $this->getReference('CPU-i3-1150');
$disk = $this->getReference('Disk-wd500blue');

//...

$testComputer->setCpu($cpu);        // OK
$testComputer->addDisk($disk);      // OK
$testComputer->addDisk($disk);      // ERROR

正如预期的那样,我得到的错误是违反完整性约束:

[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-14'
for key 'PRIMARY' 

我该如何克服这个问题?我想我应该以某种方式在连接表上添加一个索引,但我不知道这是否可能。

编辑:我也尝试过——只是为了——单向关系,同样的错误。

【问题讨论】:

    标签: php entity-framework symfony doctrine-orm


    【解决方案1】:

    你不能用标准的ManyToMany Doctrine 关系做你想做的事情,因为根据定义,这些关系是唯一的,即它们只包含两个实体的唯一组合。

    但是您可以使用“关联”实体来做到这一点,该实体充当两个实体的中间:

    class Computer { 
        /** 
         * @ORM\OneToMany(targetEntity="ComputerDisk", mappedBy="computer") 
         **/ 
        protected $computerDisks; 
    } 
    
    class ComputerDisk { 
        /** 
         * @ORM\ManyToOne(targetEntity="Computer", inversedBy="computerDisks") 
         * @ORM\JoinColumn(name="computer_id", referencedColumnName="id") 
         **/ 
        protected $computer; 
    
        /** 
         * @ORM\ManyToOne(targetEntity="Disk", inversedBy="computerDisks") 
         * @ORM\JoinColumn(name="disk_id", referencedColumnName="id") 
         **/ 
        protected $disk; 
    
    } 
    
    class Disk { 
        /** 
         * @ORM\OneToMany(targetEntity="ComputerDisk", mappedBy="disk") 
         **/ 
        protected $computerDisks; 
    } 
    

    这将类似于多对多关系,只是这个中间实体将用于保存关系并且它不必是唯一的。

    在您的情况下,该实体与磁盘之间的关系可能是单向的,因为您可能不需要知道哪些计算机拥有每个磁盘,因此 Disk 实体中的字段和与该实体关联的 ComputerDisk 中的 inversedby 可以被忽略

    这种方法的一个优点是关系可以包含额外的字段,因此您可以做一些事情,例如拥有一个保存磁盘位置的 $diskBay 字段

    【讨论】:

    • 非常感谢卡洛斯,事实上我在另一个问题中听说过“Joiner 类”。这很有帮助。我也想以 Sonata Admin 形式管理它,即有一个“添加磁盘”按钮,但我想这不是微不足道的。如果我为此打开另一个问题,也许会更好?你有什么经验吗?
    • 首先尝试实现它,如果你不能让它工作,打开一个不同的问题
    猜你喜欢
    • 1970-01-01
    • 2017-12-02
    • 2014-11-20
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多