我必须首先确定我是 Doctrine 的新手,尽管我对 SQL 和 PHP/Symfony 2 有足够的了解。
所以,我创建了这个与 SQL 表关联的 IssueType 实体:
/**
* IssueType
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\IssueTypeRepository")
*/
class IssueType
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
// Getters, setters...
}
我填充了它,所以该表的内容现在是:
id | name
1 | Bande dessinée
2 | Livre
3 | Film
4 | Disque
现在我有了另一个实体 Role,它使用一个复合键,由一个常规字符串(名称)和一个外键(来自 IssueType 的 id)组成:
/**
* Role
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\RoleRepository")
*/
class Role
{
/**
* @var IssueType
*
* @ORM\ManyToOne(targetEntity="Blog\Bundle\CoreBundle\Entity\IssueType")
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $issueType;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
* @ORM\JoinColumn(nullable=false)
* @ORM\Id
*/
private $name;
// Getters, setters...
}
这两个表都是由数据库中的教义正确生成的。但是,尽管它应该是微不足道的,但我终其一生都找不到在这种情况下正确且成功的持久化操作的单个示例。
我尝试做的是以下内容:
$manager = $this->getDoctrine()->getManager();
$issueType = new IssueType();
$issueType->setId(1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
因此,我尝试坚持以下内容:
Role: {
IssueType: {id: 1, name: ''},
name: 'Dessinateur',
}
我得到的是这个讨厌的例外:
Entity of type Blog\Bundle\CoreBundle\Entity\Role has identity through a foreign entity Blog\Bundle\CoreBundle\Entity\IssueType, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'Blog\Bundle\CoreBundle\Entity\Role'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.
我知道它希望我首先持久化外部实体,但我不想这样做,因为数据库中已经存在 ID#1 的外部问题类型,因此不需要持久化。当我没有在注释中指定任何“级联”属性时,它怎么会问我呢?
BTY 我无论如何都尝试按照它说的去做,但最终会出现重复输入错误。
那么,我应该怎么做才能让 Doctrine 明白不应该坚持外国问题类型呢?
编辑
artmees 提出了以下解决方案,效果很好:
$manager = $this->getDoctrine()->getManager();
$issueType = $manager->getRepository('BlogCoreBundle:IssueType')->find(1);
$role = new Role();
$role->setIssueType($issueType);
$role->setName('Dessinateur');
$manager->persist($role);
$manager->flush();
然而,这意味着向数据库发出额外的请求,如果不使用 Doctrine,这本可以避免。由于我已经知道要使用的外部 ID,有没有办法直接将它与persist() 一起使用,而不需要像实际从数据库中检索完整对象这样的长度?