我用两个模型做了一个非常基本的例子。
"歌手"延伸自" Person"
我正在使用class table Inheritance这两个模型:
<?php
namespace models;
/**
* @Table(name="persons")
* @entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="type", type="string")
* @DiscriminatorMap({"singer" = "\models\Singer"})
*/
abstract class Person {
/**
* @Id
* @Column(type="integer", nullable=false, name="id_person")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/** @column(type="string", nullable=false) */
protected $name;
歌手模特看起来像:
namespace models;
/**
* @Table(name="singers")
* @entity
*/
class Singer extends Person{
/** @column(type="string", nullable=false) */
protected $gender;
}
考虑这种情况。
在db中我有这些行:
人员表:
id_person | name | type
-----------------------
1 john singer
歌手表:
id_person | gender
------------------
1 pop
我继续删除这位歌手:
$singer = $em->find('models\Singer', 1);
$em->remove($singer);
$em->flush();
执行上面的代码后,我再次检查数据库,我发现了这个:
人员表:
id_person | name | type
-----------------------
(empty)
歌手表:
id_person | gender
------------------
1 pop
如您所知,未按预期删除子表中的行。
因此,在搜索了学说文档之后,它说:
如果不使用SchemaTool生成所需的SQL,则应该知道删除类表继承会在所有数据库实现中使用外键属性ON DELETE CASCADE。如果未能自行实现,将导致数据库中出现死行。
所以,我继续改变人员表如下:
ALTER TABLE persons
ADD CONSTRAINT fk_persons_1
FOREIGN KEY (id_person)
REFERENCES singers (id_person)
ON DELETE CASCADE
ON UPDATE NO ACTION;
现在,问题变得复杂了:
当我尝试插入像
这样的新歌手时$singer = new \models\Singer('Zara', 'rock');
$em->persist($singer);
$em->flush();
它引发了异常:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`practica`.`persons`, CONSTRAINT `fk_persons_1` FOREIGN KEY (`id_person`) REFERENCES `singers` (`id_person`) ON DELETE CASCADE ON UPDATE NO ACTION)' in /var/www/html/doctrine/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php:138 Stack trace: #0 /var/www/html/doctrine/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php(138): PDOStatement->execute(NULL) #1 /var/www/html/doctrine/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php(165): Doctrine\DBAL\Statement->execute() #2 /var/www/html/doctrine/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(929): Doctrine\ORM\Persisters\JoinedSubclassPersister->executeInserts() #3 /var/www/html/doctrine/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(318): Doctrine\ORM\UnitOfWork->executeInserts(Object(Doctrine\ORM\Mapping\ClassMetadata)) #4 /var/www/html/doctrine/vendor/doct in /var/www/html/doctrine/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php on line 47
所以,基本上,我需要的是在MySQL db中删除子表中的信息。但是我没理解。
答案 0 :(得分:1)
尝试撤消FOREIGN KEY
,即将其从人员表中移除并将其添加到您的歌手表中
ALTER TABLE singers
ADD CONSTRAINT fk_singers_1
FOREIGN KEY (id_person)
REFERENCES persons (id_person)
ON DELETE CASCADE
ON UPDATE NO ACTION;
答案 1 :(得分:0)
我想你可能不得不问自己是否真的需要一个与多个表有关的字段。
在任何情况下,最好通过关系而不是使用继承和鉴别器映射来实现,这对使用相同表的对象很有效,但因为在你的情况下它们是不同的表,所以最好使用它相反的关系:
<?php
namespace models;
/**
* @Table(name="persons")
* @entity
*/
class Person {
/**
* @Id
* @Column(type="integer", nullable=false, name="id_person")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/** @column(type="string", nullable=false) */
protected $name;
/**
* @OneToOne(targetEntity="Singer")
* @JoinColumn(name="id_person", referencedColumnName="id_person")
*/
private $singer;
namespace models;
/**
* @Table(name="singers")
* @entity
*/
class Singer{
/**
* @Id
* @Column(type="integer", nullable=false, name="id_person")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/** @column(type="string", nullable=false) */
protected $gender;
/**
* @OneToOne(targetEntity="Person", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
* @JoinColumn(name="id_person", referencedColumnName="id_person")
*/
private $person;
}
通过尝试将设计附加到现实世界,您将使实现变得复杂,这将使您的应用程序难以保留。 我没有尝试代码(可能需要调整)。