我希望这是一个直接的过程,但似乎Doctrine不太喜欢通过它们的id链接实体的想法。
所有我打算做的是标准化一个表,从它运送一些字段到一个新的表,而不是添加一个新的引用字段到原来的表中,以保持新的对应记录的ID,确保在子表中的新记录将具有相同的ID,它的父行。
下面是我所拥有的一个例子:
一个User实体,带注释字段$user
引用UserDetail实体中的列ID到它自己的ID
/**
* @ORM'Table(name="user", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
* @ORM'Entity
*/
class User extends Entity
{
/**
* @var integer
*
* @ORM'Column(name="id", type="integer", nullable=false)
* @ORM'Id
* @ORM'GeneratedValue(strategy="IDENTITY")
*/
private $id
/**
* @ORM'OneToOne(targetEntity="UserDetail", cascade={"persist"})
* @ORM'JoinColumn(name="id", referencedColumnName="id", nullable=true)
*/
private $userDetail;
...
}
这里是UserDetail删除了ID的@GeneratedValue
/**
* @ORM'Table(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
* @ORM'Entity
*/
class UserDetail extends Entity
{
/**
* @var integer
*
* @ORM'Column(name="id", type="integer", nullable=false)
* @ORM'Id
*/
private $id;
...
}
在这一点上,我的期望是能够做这样的事情:
$user = new User();
$userDetail = new UserDetail();
$user->setUserDetail($userDetail)
$entityManager->persist($user);
$entityManager->flush();
并获得两个记录持久化到user和user_detail表中,它们具有相同的 ID,但现实是,没有为UserDetail的标识符定义任何策略,doctrine将抱怨缺少ID, Entity of type UserDetail is missing an assigned ID for field 'id'.
当然也可以手动完成这项工作,并且在多个调用中
$user = new User();
$entityManager->persist($user);
$entityManager->flush();
$userDetail = new UserDetail();
$userDetail->setId($user->getId)
$user->setUserDetail($userDetail)
$entityManager->persist($user);
$entityManager->flush();
但是我仍然希望有一个正确的配置(注释)可以帮助我避免这些额外的步骤,并通过实体的id将一对一关系的处理留给Doctrine。
这是未经测试的,但我认为以下可能工作,根据文档(http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html):
) /**
* @ORM'Table(name="user_detail", options={"collate"="utf8_general_ci", "charset"="utf8", "engine"="InnoDB"})
* @ORM'Entity
*/
class UserDetail extends Entity
{
/**
* @var integer
*
* @ORM'OneToOne(targetEntity="User")
* @ORM'JoinColumn(name="id", referencedColumnName="id")
* @ORM'Id
*/
private $user;
...
}
我成功地创建了一个一对一的关系,其中主键也是外键。见下文:
汽车实体:
/**
* @ORM'Table(name="cars")
* @ORM'Entity(repositoryClass="App'Repository'CarRepository")
*/
class Car
{
/**
* @ORM'OneToOne(targetEntity="CarConfiguration", mappedBy="car")
*/
private ?CarConfiguration $carConfiguration = null;
public function getCarConfiguration(): ?CarConfiguration
{
return $this->carConfiguration;
}
public function setCarConfiguration(CarConfiguration $carConfiguration): void
{
$this->carConfiguration = $carConfiguration;
}
}
Car Configuration实体:
/**
* @ORM'Table(name="car_configurations")
* @ORM'Entity()
*/
class CarConfiguration
{
/**
* @ORM'Id
* @ORM'JoinColumn(name="car_id", referencedColumnName="id", unique=true, nullable=false, onDelete="CASCADE")
* @ORM'OneToOne(targetEntity="Car", inversedBy="carConfiguration", cascade={"all"})
*/
private Car $car;
/**
* @ORM'Column(name="has_radio", type="boolean")
*/
private bool $hasRadio;
public function __construct(Car $car, bool $hasRadio = false)
{
$this->car = $car;
$this->hasRadio = $hasRadio;
}
public function getCar(): Car
{
return $this->car;
}
public function hasRadio(): bool
{
return $this->hasRadio;
}
public function setHasRadio(bool $hasRadio): void
{
$this->hasRadio = $hasRadio;
}
}
Car存储库:
class CarRepository extends EntityRepository
{
public function persist(Car $car): void
{
$entityManager = $this->getEntityManager();
$entityManager->persist($car);
}
public function flush(): void
{
$entityManager = $this->getEntityManager();
$entityManager->flush();
}
}
客户端代码:
class AwesomeCommand extends Command
{
private CarRepository $carRepository;
public function __construct(CarRepository $carRepository) {
parent::__construct();
$this->carRepository = $carRepository;
}
protected function execute(InputInterface $input, OutputInterface $output): void
{
$car = $this->carRepository->find(1234);
$carConfiguration = new CarConfiguration($car, true);
$car->setCarConfiguration($carConfiguration);
$this->carRepository->persist($car);
$this->carRepository->flush();
}
}
链接:https://www.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html use-case-2-simple-derived-identity