为什么我的级联不起作用? - 完整性约束违规

时间:2017-03-02 17:40:52

标签: php mysql doctrine-orm foreign-keys symfony

我有父子实体,父母是图像,孩子是图像投票

class Image {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\Column(type="string", length=255, name="file_name")
     * @var string $fileName
     */
    protected $fileName;

    /**
     * @ORM\Column(type="string", length=255, name="title", nullable=true)
     * @var string $title
     */
    protected $title = null;

    /**
     * @ORM\Column(type="string", length=255, name="author", nullable=true)
     * @var string $author
     */
    protected $author = null;

    /**
     * @ORM\Column(type="datetime", name="upload_at")
     */
    protected $uploadDate;

    /**
     * @ORM\Column(type="boolean", name="in_pool")
     */
    protected $inPool;

    /**
    * One image has many votes
    * @ORM\OneToMany(targetEntity="Vote", mappedBy="image")
    */
    private $votes;

子:

class Vote
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
    /**
     * @ORM\ManyToOne(targetEntity="Image", inversedBy="votes")
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    protected $image;

    /**
     * @ORM\Column(type="datetime", name="date")
     */
    protected $date;

    /**
     * This is internal variable, it does not have to be mapped into database field
     * @var int Counter of votes for an Image
     */
    private $counter;

如您所见,我在实体中设置了@ORM\JoinColumn(onDelete="CASCADE")

然而,当我尝试删除有投票的图像时,我得到了这个:

  

执行' DELETE FROM image时发生异常WHERE id =?'   与params [24]:

     

SQLSTATE [23000]:完整性约束违规:1451无法删除或   更新父行:外键约束失败(konkursvote,   CONSTRAINT FK_5A1085643DA5256D FOREIGN KEY(image_id)参考   imageid))

用于删除基于id的图像的代码如下所示:

/**
* @Route("/admin/removeimage/{id}", name="admin-remove-image")
*/
public function adminRemoveImage($id)
{

    $em = $this->getEm();
    $image = $em->getRepository('AppBundle:Image')->findOneById($id);
    $fileName = $image->getFileName();

    $em->remove($image);
    $em->flush();

    unlink('uploads/'.$fileName);
    unlink('media/cache/my_thumb/uploads/'.$fileName);

    return $this->redirectToRoute('admin-panel');
}

有人能告诉我为什么这种关系会失败吗?

更新 以下是使用SHOW CREATE TABLE vote

的输出
  

|投票| CREATE TABLE voteid int(11)NOT NULL   AUTO_INCREMENT,date datetime NOT NULL,image_id int(11)   DEFAULT NULL,PRIMARY KEY(id),KEY IDX_5A1085643DA5256D   (image_id),CONSTRAINT FK_5A1085643DA5256D FOREIGN KEY   (image_id)参考imageid))ENGINE = InnoDB   AUTO_INCREMENT = 14 DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci |

1 个答案:

答案 0 :(得分:1)

添加@ORM\JoinColumn(onDelete="CASCADE")是教条通过doctrine:schema:updatedoctrine:schema:create管理的表格的映射。

除非发出上述命令,否则级联外键引用不会自动应用于数据库表列。

默认情况下,创建外键引用时,它设置为ON DELETE RESTRICT

要解决您的问题,请运行以下SQL命令:

ALTER TABLE `vote` DROP FOREIGN KEY `FK_5A1085643DA5256D`;

ALTER TABLE `vote` ADD CONSTRAINT `FK_5A1085643DA5256D` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`) ON DELETE CASCADE;

与跑步相同:

php bin/console doctrine:schema:update --force

但是,架构更新可能会对数据库结构造成不可逆转的更改/损坏。

请参阅:http://symfony.com/doc/current/doctrine.html#creating-the-database-tables-schema

我还建议运行php bin/console doctrine:schema:update --dump-sql以确定编辑学说实体映射的其他潜在错误配置。

或者正如@Cerad所提到的,你可以通过使用cascade={"remove"}来告诉Doctrine管理关系,而不依赖于外键引用。

class Image 
{
    //...

    /**
    * One image has many votes
    * @ORM\OneToMany(targetEntity="Vote", mappedBy="image", cascade={"remove"})
    */
    private $votes;
}

这将告诉symfony在删除Vote实体时为Image实体关联的Image实体集合发出删除语句。

有一点需要注意,这只适用于针对Entity管理器发出命令,而不是DBAL查询构建器。

参考:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#removing-entities