【发布时间】:2015-05-22 17:02:00
【问题描述】:
我有 User 和 UserProfile OneToOne 相关的 Doctrine ORM 实体。它们应该始终成对存在,没有UserProfile,就不应该有User。
用户应该从自动增量获取它的 id,而 UserProfile 应该有用户的 id。所以他们都应该有相同的 id 并且没有其他列来建立关系 (Doctrine docs: Identity through foreign Entities)。
UserProfile 的 id 同时是主键 (PK) 和外键 (FK)。
我设法设置了它,但它要求先保存用户,然后才在单独的步骤中创建和保存 UserProfile。
我想要的是在构造函数中始终使用 User 创建 UserProfile,但如果我这样做,我会得到这个异常:
Doctrine\ORM\ORMInvalidArgumentException: The given entity of type 'AppBundle\Entity\UserProfile' (AppBundle\Entity\UserProfile@0000000052e1b1eb00000000409c6f2c) has no identity/no id values set. It cannot be added to the identity map.
请看下面的代码——它可以工作,但不是我想要的方式。 php cmets 显示了我想要实现的目标。
Test.php:
/**
* It works, both saving and loading.
* BUT, it requires that I create and save UserProfile
* in a separate step than saving User step.
*/
// create and save User
$user = new User();
$objectManager->persist($user);
$objectManager->flush();
// create and save UserProfile (this should be unnecessary)
$user->createProfile()
$objectManager->flush();
User.php:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\UserRepository")
* @ORM\Table(name="users")
*/
class User
{
/**
* @var int
*
* @ORM\Column(name="uid", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* It's NULL at first, I create it later (after saving User).
*
* @var UserProfile|null
*
* @ORM\OneToOne(targetEntity="UserProfile", mappedBy="user", cascade="persist")
*/
private $profile = null;
public function __construct()
{
// I want to create UserProfile inside User's constructor,
// so that it is always present (never NULL):
//$this->profile = new UserProfile($this);
// but this would give me error:
//
// Doctrine\ORM\ORMInvalidArgumentException:
// The given entity of type 'AppBundle\Entity\UserProfile'
// (AppBundle\Entity\UserProfile@0000000058af220a0000000079dc875a)
// has no identity/no id values set. It cannot be added to the identity map.
}
public function createProfile()
{
$this->profile = new UserProfile($this);
}
}
UserProfile.php:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="profiles")
*/
class UserProfile
{
/**
* – UserProfile's "uid" column points to User's "uid" column
* – it is PK (primary key)
* - it is FK (foreign key) as well
* – "owning side"
*
* @var User
*
* @ORM\Id
* @ORM\OneToOne(targetEntity="User", inversedBy="profile")
* @ORM\JoinColumn(name="uid", referencedColumnName="uid", nullable=false)
*/
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
}
【问题讨论】:
-
Id 是一个数据库的东西,不应该成为模型中的一个问题。放弃他们需要相同主键值的想法。或者如果做不到这一点,请放弃一个需要是自动的而另一个不需要的概念。
-
@Cerad 我正在构建一个遗留应用程序——数据库就是它的样子。我需要将 Doctrine 调整为当前模式,反之亦然……另外,上面的代码有效。 Doctrine 可以处理作为主键的外键。它只是不能一次刷新实体。或者至少我正在寻找答案,如何配置 Doctrine 以便它可以。
-
很公平。如果您进行搜索,那么您会发现同一问题的数百个变体。答案都一样。
-
看来您需要更改关系的拥有方。
标签: php symfony doctrine-orm doctrine