鉴于我有2个类,User和UserId看起来像这样:
<?php
class UserId {
/** @var int */
private $value;
public function __construct($value) {
$this->value = (int) $value;
}
}
class User {
/** @var UserId */
private $id;
private $firstName;
private $lastName;
public function __construct(UserId $id, $firstName, $lastName) {
$this->id = $id;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
User:
id : INT PK
firstName: VARCHAR
lastName: VARCHAR
在调用“find()”时,是否可以告诉学说用UserId生成一个用户?
答案 0 :(得分:3)
是的,这是可能的,我会进一步解释。
简单方法
首先我必须说,对于这个简单的用例,answer provided by Andresch Serj就足够了。
使用构造函数设置UserId
对象,如果它尚不存在,则通过懒惰实例化来获取UserId
对象:
class User
{
/**
* @var UserId
*/
private $userId;
/**
* @var int
*/
private $id;
/**
* @param UserId $userId
* ...
*/
public function __construct(UserId $userId /* ... */)
{
$this->userId = $userId;
$this->id = $userId->getId();
// ...
}
/**
* @return UserId
*/
public function getUserId()
{
if (!$this->userId) {
$this->userId = new UserId($this->id);
}
return $this->userId;
}
// ...
}
真正的答案
为了在加载(从数据库中获取)实体时操作它,您可以使用Doctrine的PostLoad
事件。
首先创建一个侦听器,它将创建一个新的UserId
对象并将其设置在User
实体上:
use Doctrine\ORM\Event\LifecycleEventArgs;
class UserListener
{
/**
* @param User $user
* @param LifecycleEventArgs $event
* @return void
*/
public function postLoad(User $user, LifecycleEventArgs $event)
{
$userId = new UserId($user->getId());
$user->setUserId($userId);
}
}
然后重构getUserId()
User
方法以简单地返回UserId
对象。添加setUserId()
方法(确保无法换出已存在的UserId
对象是明智的。还要注意@EntityListeners
注释,它告诉Doctrine这个实体有一个监听器:
/**
* @EntityListeners({"UserListener"})
*/
class User
{
/**
* @return UserId
*/
public function getUserId()
{
return $this->userId;
}
/**
* @param UserId $userId
* @return void
* @throws RuntimeException
*/
public function setUserId(UserId $userId)
{
if ($this->userId) {
throw new RuntimeException("UsedId already present, you can't swap it!");
}
$this->userId = $userId;
}
// ...
}
最后,在应用程序的配置/引导阶段,您应该注册监听器:
$listener = new UserListener();
$em->getConfiguration()->getEntityListenerResolver()->register($listener);
现在,只要Doctrine加载User
实体,就会在其中插入UserId
个对象。此设置对于比您描述的更高级的用例非常有用。
答案 1 :(得分:0)
如果您只需要您的用户对象能够提供UserID对象,您可以将其添加为私有属性并添加公共getter:
private $userIdObject;
public function __construct(UserId $id, $firstName, $lastName)
{
$this->id = $id; = $id->id;
$this->userIdObject = $id;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function getUserId()
{
return $this->userIdObject();
}
知道你为什么需要它真的很有帮助。 我的意思是:Doctrine是一个数据库的演示文稿。如果要将id存储为整数,则无需将其作为对象。 如果你需要一个Object用id来做某些事情(生成它,操纵它...... )你可以在你的用户对象中有一个getter来为你生成所述对象。
public function getUserId()
{
return new UserId($this->id);
}
或者您可以拥有在Helper类或服务中操作UserId所需的所有方法。