[英]Default value of Doctrine ORM association
我有实体(如下所示)。 我想在创建时设置一些默认值。 正如您在__construct
中看到的那样,设置$name
(字符串)很容易,但是如何设置$group
? (例如,我知道数据库中有一个id=122
的组)
/**
* @ORM\Entity
*/
class Person {
private $id;
/** @ORM\Column(type="string") */
private $name;
/**
* @ORM\ManyToOne(targetEntity="Group", inversedBy="persons")
* @ORM\JoinColumn(referencedColumnName="id")
*/
private $group;
public function setGroup(Group $group)
{
$this->group = $group;
$group->addPerson($this);
}
// ... setters/getters
//construct default Person
public function __construct()
{
$this->setName("Mike");
$this->setGroup($EXISTING_GROUP_FROM_MY_DB); // <<--------------
}
}
我同意 moonwave99 的观点,这是糟糕的设计。 在这里,您正试图从一个不支持容器的地方(即它不知道,也不应该知道 Doctrine)访问数据库(通过 Doctrine 服务)。
我最近有一个类似的问题......实际上几乎完全相同的问题。 但我不希望这个逻辑在控制器内部。 所以我写了一个服务来处理用户创建。 我让该服务访问它唯一需要的其他服务:Doctrine。
这是一个示例,其中创建了具有所有可用角色的用户:
namespace MyBundle\Entity;
class UserFactory
{
private $doctrine;
public function __construct($doctrine)
{
$this->doctrine = $doctrine;
}
public function generateNewUser($email, $password)
{
$user = new User();
// Since you have access to the Doctrine service, you can use $this->doctrine
// to do anything you would normally do in your controller with $this->getDoctrine()
$roles = $this->doctrine->getEntityManager()->getRepository("MyBundle:Role")->findAll();
foreach ($roles as $role)
{
$user->addRole($role);
}
return $user;
}
}
现在在config.yml
或services.yml
中注册该服务,记住将 Doctrine 服务传递给它:
services:
mybundle.factory.user:
class: MyBundle\Entity\UserFactory
arguments: ['@doctrine']
就是这样......现在,在你的控制器中,你可以通过以下方式创建一个新用户:
public function MyController()
{
$user = $this->get("mybundle.factory.user")->generateNewUser("someone@email.com", "password123");
}
推荐的方法是在构造函数参数中要求关联的实体对象,可选地与实体存储库等工厂结合,以在实例化期间提供Group
实体。 这确保实体始终处于有效状态。
src/实体/Person.php
namespace App\Entity;
/**
* @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
*/
class Person
{
//...
public function __construct($name, Group $group)
{
$this->setName($name);
$this->setGroup($group);
}
//...
}
src/Repsotory/PersonRepository.php
namespace App\Repsotory;
use App\Entity\Group;
use App\Entity\Person;
class PersonRepository
{
const DEFAULT_GROUP = 122;
public function create($name, Group $group = null)
{
if (null === $group) {
$group = $this->_em->getReference(Group::class, self::DEFAULT_GROUP);
}
$person = new Person($name, $group);
$this->_em->persist($person);
return $person;
}
}
这允许您完全依赖 Doctrine ORM 实体管理器来维护默认的组关联。
$person = $em->getRepository(Person::class)->create('Mike');
$group = $person->getGroup();
echo $group->getId(); //outputs: 122
$em->flush();
这种方法可以在 Symfony 中扩展以使用查询服务而不是原则实体存储库,以提供处理实体实例化的中央位置。
在 Symfony 3.4+ 中,您可以使用存储库服务为存储库提供依赖注入,而不是使用
EntityManagerInterface
。
src/服务/PersonCreateQuery.php
namespace App\Service;
use App\Entity\Group;
use App\Entity\Person;
use Doctrine\ORM\EntityManagerInterface;
class PersonCreateQuery
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function __invoke($name)
{
$group = $this->em->getReference(Group::class, 122);
$person = new Person($name, $group);
$this->em->persist($person);
return $person;
}
}
现在您可以使用依赖注入来检索查询服务并根据需要使用它,例如使用 Symfony Form 或 Controller。
namespace App\Controller;
use App\Service\PersonCreateQuery;
class PersonController
{
public function createAction(PersonCreateQuery $query)
{
$person = $query('Mike');
$this->getDoctrine()->getManager()->flush();
//...
}
}
注意:
$em->getReference()
的用法可以替换为$em->find()
。 使用$em->getReference()
将阻止对数据库的查询,但如果引用无效将抛出异常,而使用$em->find()
将返回null
。
另一种方法是使用实体中的生命周期回调或事件监听器来执行更复杂的功能。 但是,这将导致您的实体在被持久化之前以无效状态被实例化。
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class Person
{
const DEFAULT_GROUP = 122;
/** @ORM\Column(type="string") */
private $name = 'Mike';
/**
* @ORM\ManyToOne(targetEntity="Group", inversedBy="persons")
* @ORM\JoinColumn(referencedColumnName="id")
*/
private $group;
//....
public function setGroup(Group $group)
{
$this->group = $group;
$group->addPerson($this);
}
/**
* @param LifecycleEventArgs $event
* @ORM\PrePersist
*/
public function onPrePersist(LifecycleEventArgs $event)
{
if (!$this->group instanceof Group) {
/** set default group if not specified */
$group = $event->getEntityManager()->getReference(Group::class, self::DEFAULT_GROUP);
$this->setGroup($group);
}
}
}
现在,当您保留一个 Person 实体时,如果没有在其他地方明确设置,它将添加该组。
$person = new Person();
$person->setName('Foo Bar');
$em->persist($person); //persist or do nothing if already persisted
$group = $person->getGroup();
echo $group->getId(); //outputs: 122
$groupPerson = $group->getPerson();
echo $groupPerson->getName(); //outputs: Foo Bar
$em->flush(); //save to database
为了理智,这里是教义事件文档的链接:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.