У меня есть объект (например, ниже). Я хочу установить некоторые значения по умолчанию при создании. Как вы можете видеть в __construct
, легко установить $name
(string), но как я могу установить $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).
Недавно у меня была аналогичная проблема … в значительной степени такая же точная проблема, на самом деле. Но я не хотел, чтобы эта логика находилась внутри контроллера. Поэтому я написал сервис, чтобы заботиться о создании Пользователя. И я предоставил этот сервис для доступа к единственной другой услуге, в которой он нуждался: Доктрина.
Вот пример, когда Пользователь создается со всеми доступными Ролями:
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
, не config.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"); }
Другим методом является использование обратных вызовов Lifecycle в сущности или Event Listener для выполнения более сложных функций.
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 = self::DEFAULT_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()->find('MyBundle:Group', $this->group ?: self::DEFAULT_GROUP); $this->setGroup($group); } } }
Теперь, когда вы сохраняете объект Person, он добавит группу, если она не была явно задана в контроллере.
$person = new Person; echo $person->getName(); //outputs: Mike $person->setName('Foo Bar'); $em->persist($person); //persist or do nothing if already persisted $group = $person->getGroup(); $groupPerson = $group->getPerson(); echo $group->getId(); //outputs: 122 echo $groupPerson->getName(); //outputs: Foo Bar $em->flush(); //save to database
Для здравомыслия здесь приведены ссылки на документы для событий доктрины: