Symfony3 - 如何在多对一关系 属性 中添加默认值或保留默认值
Symfony3 - How to add default values or persist default values in a property that is a Many-to-One relation property
我有 2 个通过多对一关系关联的实体。
当我是用户输入的 persisting/storing 值时,在实际坚持之前,我有一个用户没有 populate/provide 输入的属性,我想通过代码设置它。
所以,我有登录实体:
<?php
namespace Vendor\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Logins
*
* @ORM\Table(name="logins", indexes={@ORM\Index(name="RoleID", columns={"RoleID"})})
* @ORM\Entity(repositoryClass="Vendor\MyBundle\Repository\LoginsRepository")
* @UniqueEntity(fields="email", message="Email already taken")
* @ORM\HasLifecycleCallbacks
*/
class Logins implements UserInterface, \Serializable
{
/**
* @var string
*
* @ORM\Column(name="FirstName", type="string", length=255, nullable=false)
*/
private $firstname;
/**
* @var string
*
* @ORM\Column(name="LastName", type="string", length=255, nullable=false)
*/
private $lastname;
/**
* @var string
*
* @ORM\Column(name="Email", type="string", length=255, nullable=false)
*/
private $email;
/**
* @var string
*
* @ORM\Column(name="Password", type="string", length=255, nullable=false)
*/
private $password;
/**
* @var string
*
* @ORM\Column(name="City", type="string", length=255, nullable=false)
*/
private $city;
/**
* @var \DateTime
*
* @ORM\Column(name="CreationTime", type="datetime", nullable=false)
*/
private $creationtime;
/**
* @var integer
*
* @ORM\Column(name="loginID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $loginid;
public function __toString() {
return (string)$this->loginid;
}
/**
* @var \Vendor\MyBundle\Entity\Roles
*
* @ORM\ManyToOne(targetEntity="Vendor\MyBundle\Entity\Roles", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="RoleID", referencedColumnName="roleID")
* })
*/
private $roleid;
/**
* Set firstname
*
* @param string $firstname
*
* @return Logins
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* @return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* @param string $lastname
*
* @return Logins
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* @return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set email
*
* @param string $email
*
* @return Logins
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* @param string $password
*
* @return Logins
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set city
*
* @param string $city
*
* @return Logins
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set creationtime
*
* @param \DateTime $creationtime
* @ORM\PrePersist
*
* @return Logins
*/
public function setCreationtime()
{
$this->creationtime = new \DateTime('now');
return $this;
}
/**
* Get creationtime
*
* @return \DateTime
*/
public function getCreationtime()
{
return $this->creationtime;
}
/**
* Get loginid
*
* @return integer
*/
public function getLoginid()
{
return $this->loginid;
}
/**
* Set roleid
*
* @param \Vendor\MyBundle\Entity\Roles $roleid
*
* @return Logins
*/
public function setRoleid(\Vendor\MyBundle\Entity\Roles $roleid = null)
{
$this->roleid = $roleid;
return $this;
}
/**
* Get roleid
*
* @return \Vendor\MyBundle\Entity\Roles
*/
public function getRoleid()
{
return $this->roleid;
}
public function eraseCredentials() {
}
public function getRoles() {
if ($this->roleid == '1'){
return array('ROLE_ADMIN');
}
elseif ($this->roleid == '2'){
return array('ROLE_USER');
}
}
public function getSalt() {
return null;
}
public function getUsername() {
return $this->email;
}
/** @see \Serializable::serialize() */
public function serialize() {
return serialize(array(
$this->loginid,
$this->email,
$this->password,
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized) {
list(
$this->loginid,
$this->email,
$this->password,) = unserialize($serialized);
}
}
然后是角色实体:
<?php
namespace Vendor\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Roles
*
* @ORM\Table(name="roles")
* @ORM\Entity(repositoryClass="Vendor\MyBundle\Repository\RolesRepository")
*/
class Roles
{
/**
* @var string
*
* @ORM\Column(name="RoleName", type="string", length=255, nullable=false)
*/
private $rolename;
/**
* @var boolean
*
* @ORM\Column(name="WishList", type="boolean", nullable=false)
*/
private $wishlist;
/**
* @var boolean
*
* @ORM\Column(name="Events", type="boolean", nullable=false)
*/
private $events;
/**
* @var boolean
*
* @ORM\Column(name="Reports", type="boolean", nullable=false)
*/
private $reports;
/**
* @var integer
*
* @ORM\Column(name="roleID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $roleid;
public function __toString() {
return (string)$this->getRoleid();
}
/**
* Set rolename
*
* @param string $rolename
*
* @return Roles
*/
public function setRolename($rolename)
{
$this->rolename = $rolename;
return $this;
}
/**
* Get rolename
*
* @return string
*/
public function getRolename()
{
return $this->rolename;
}
/**
* Set wishlist
*
* @param boolean $wishlist
*
* @return Roles
*/
public function setWishlist($wishlist)
{
$this->wishlist = $wishlist;
return $this;
}
/**
* Get wishlist
*
* @return boolean
*/
public function getWishlist()
{
return $this->wishlist;
}
/**
* Set events
*
* @param boolean $events
*
* @return Roles
*/
public function setEvents($events)
{
$this->events = $events;
return $this;
}
/**
* Get events
*
* @return boolean
*/
public function getEvents()
{
return $this->events;
}
/**
* Set reports
*
* @param boolean $reports
*
* @return Roles
*/
public function setReports($reports)
{
$this->reports = $reports;
return $this;
}
/**
* Get reports
*
* @return boolean
*/
public function getReports()
{
return $this->reports;
}
/**
* Get roleid
*
* @return integer
*/
public function getRoleid()
{
return $this->roleid;
}
}
这个通过注册表单处理用户输入的控制器:
<?php
namespace Vendor\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Vendor\MyBundle\Entity\Logins;
use Vendor\MyBundle\Form\UserType;
use Vendor\MyBundle\Repository\LoginsRepository;
class MainController extends Controller
{
/**
* @Route("/", name="home_page")
*/
public function indexAction(Request $request)
{
// 1) build the form
$user = new Logins();
$form = $this->createForm(UserType::class, $user);
// 2) handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 3) Encode the password
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPassword());
$user->setPassword($password);
$user->setCreationtime();
// 4) save the User!
$em = $this->getDoctrine()->getManager();
$roleid = $this->$em->getRepository('Vendor\MyBundle\Entity\Roles')->find(2); // or getReference
$user->setRoleid($roleid);
$em->persist($user);
$em->flush();
return $this->redirectToRoute('home_page');
}
return $this->render(
'VendorMyBundle:Default:index.html.twig',
array('form' => $form->createView())
);
}
简而言之,我的数据库中的角色 table 中有 2 条记录,具有主键 RoleID。
我希望当用户注册时,当我坚持并将数据刷新到数据库时,我在登录 Table 中的 RoleID 列 (FK) 默认填充值 2。
任何见解或替代方案都将受到赞赏。我在 Symfony 3.0.1 上。
我可以想到 2 种可能的解决方案来自动执行此操作。两者都使用 doctrine pre-persist event.
通过添加带有@ORM\PrePersist
注解的回调方法为实体添加pre-persist方法,并通过添加@ORM\HasLifecycleCallbacks
注解标记实体具有生命周期回调(read also here for more details on how to do this).
Here you can find Symfony specific documentation on the life cycle callback
/**
* @ORM\PrePersist
* @param \Doctrine\ORM\Event\LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
$entity= $args->getEntity();
if($entity->getRoleid() === null){
$entityManager = $args->getEntityManager();
$roleId = $entityManager->getReference(\Vendor\MyBundle\Entity\Roles::class, 2);
$entity->setRoleId($roleId);
}
}
注意:您也可以使用方法find
代替getReference
,但使用getReference
会节省您额外的往返时间到数据库。你说你有两个角色,如果你知道它们总是存在(固定装置),那么就没有必要解决它们。
但您也可以在外部侦听器(称为事件订阅者)中执行相同的操作。 Check here the Doctrine 2 documentation on this topic。
Here you can find Symfony specific documentation on the event subscriber。
namespace Vendor\MyBundle\Listener;
use Doctrine\ORM\Events;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\Common\EventSubscriber;
class DefaultRoleListener implements EventSubscriber
{
/**
* @return array
*/
public function getSubscribedEvents()
{
return array(
Events::prePersist,
);
}
/**
* @param LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if( $entity instanceof Login) {
if($entity->getRoleid() === null){
$entityManager = $args->getEntityManager();
$roleId = $entityManager->getReference(\Vendor\MyBundle\Entity\Roles::class, 2);
$entity->setRoleId($roleId);
}
}
}
}
您需要附加您的侦听器(事件订阅者)。
$entityManager = // get your entity manager instance
$doctrineEventManager = $entityManager->getEventManager();
$defaultRoleListener = // get your listener instance
$doctrineEventManager->addEventSubscriber($defaultRoleListener);
但也许有一种 Symfony 方法可以做到这一点...我主要使用 Zend Framework。
两种解决方案的作用完全相同。这完全取决于您个人对逻辑存储位置的偏好;在您的实体中或在单独的侦听器中。
更新
如果你有问题让它工作,请确保你首先删除 \Vendor\MyBundle\Resources\config\
中任何现有的 YML/XML 文件,因为这些可能导致 Doctrine 忽略你的 prePersist
方法。
我忘记了什么。对于第一个解决方案,您还需要标记该实体具有生命周期回调。您可以通过添加注释 @HasLifecycleCallbacks
来完成此操作。并检查您是否在该方法上添加了 @PrePersist
。根据您的设置,您有时需要使用 @ORM\HasLifecycleCallbacks
或 @ORM\PrePersist
。你应该喜欢你的其他 @Entity
注释。
不确定为什么您收到评论中提到的错误消息。但是你可以反其道而行之,将我在回答中写的行换成你的控制器代码中的行,如果它们对你有用...
我有 2 个通过多对一关系关联的实体。 当我是用户输入的 persisting/storing 值时,在实际坚持之前,我有一个用户没有 populate/provide 输入的属性,我想通过代码设置它。
所以,我有登录实体:
<?php
namespace Vendor\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Logins
*
* @ORM\Table(name="logins", indexes={@ORM\Index(name="RoleID", columns={"RoleID"})})
* @ORM\Entity(repositoryClass="Vendor\MyBundle\Repository\LoginsRepository")
* @UniqueEntity(fields="email", message="Email already taken")
* @ORM\HasLifecycleCallbacks
*/
class Logins implements UserInterface, \Serializable
{
/**
* @var string
*
* @ORM\Column(name="FirstName", type="string", length=255, nullable=false)
*/
private $firstname;
/**
* @var string
*
* @ORM\Column(name="LastName", type="string", length=255, nullable=false)
*/
private $lastname;
/**
* @var string
*
* @ORM\Column(name="Email", type="string", length=255, nullable=false)
*/
private $email;
/**
* @var string
*
* @ORM\Column(name="Password", type="string", length=255, nullable=false)
*/
private $password;
/**
* @var string
*
* @ORM\Column(name="City", type="string", length=255, nullable=false)
*/
private $city;
/**
* @var \DateTime
*
* @ORM\Column(name="CreationTime", type="datetime", nullable=false)
*/
private $creationtime;
/**
* @var integer
*
* @ORM\Column(name="loginID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $loginid;
public function __toString() {
return (string)$this->loginid;
}
/**
* @var \Vendor\MyBundle\Entity\Roles
*
* @ORM\ManyToOne(targetEntity="Vendor\MyBundle\Entity\Roles", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="RoleID", referencedColumnName="roleID")
* })
*/
private $roleid;
/**
* Set firstname
*
* @param string $firstname
*
* @return Logins
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* @return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* @param string $lastname
*
* @return Logins
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* @return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* Set email
*
* @param string $email
*
* @return Logins
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* @param string $password
*
* @return Logins
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set city
*
* @param string $city
*
* @return Logins
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set creationtime
*
* @param \DateTime $creationtime
* @ORM\PrePersist
*
* @return Logins
*/
public function setCreationtime()
{
$this->creationtime = new \DateTime('now');
return $this;
}
/**
* Get creationtime
*
* @return \DateTime
*/
public function getCreationtime()
{
return $this->creationtime;
}
/**
* Get loginid
*
* @return integer
*/
public function getLoginid()
{
return $this->loginid;
}
/**
* Set roleid
*
* @param \Vendor\MyBundle\Entity\Roles $roleid
*
* @return Logins
*/
public function setRoleid(\Vendor\MyBundle\Entity\Roles $roleid = null)
{
$this->roleid = $roleid;
return $this;
}
/**
* Get roleid
*
* @return \Vendor\MyBundle\Entity\Roles
*/
public function getRoleid()
{
return $this->roleid;
}
public function eraseCredentials() {
}
public function getRoles() {
if ($this->roleid == '1'){
return array('ROLE_ADMIN');
}
elseif ($this->roleid == '2'){
return array('ROLE_USER');
}
}
public function getSalt() {
return null;
}
public function getUsername() {
return $this->email;
}
/** @see \Serializable::serialize() */
public function serialize() {
return serialize(array(
$this->loginid,
$this->email,
$this->password,
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized) {
list(
$this->loginid,
$this->email,
$this->password,) = unserialize($serialized);
}
}
然后是角色实体:
<?php
namespace Vendor\MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Roles
*
* @ORM\Table(name="roles")
* @ORM\Entity(repositoryClass="Vendor\MyBundle\Repository\RolesRepository")
*/
class Roles
{
/**
* @var string
*
* @ORM\Column(name="RoleName", type="string", length=255, nullable=false)
*/
private $rolename;
/**
* @var boolean
*
* @ORM\Column(name="WishList", type="boolean", nullable=false)
*/
private $wishlist;
/**
* @var boolean
*
* @ORM\Column(name="Events", type="boolean", nullable=false)
*/
private $events;
/**
* @var boolean
*
* @ORM\Column(name="Reports", type="boolean", nullable=false)
*/
private $reports;
/**
* @var integer
*
* @ORM\Column(name="roleID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $roleid;
public function __toString() {
return (string)$this->getRoleid();
}
/**
* Set rolename
*
* @param string $rolename
*
* @return Roles
*/
public function setRolename($rolename)
{
$this->rolename = $rolename;
return $this;
}
/**
* Get rolename
*
* @return string
*/
public function getRolename()
{
return $this->rolename;
}
/**
* Set wishlist
*
* @param boolean $wishlist
*
* @return Roles
*/
public function setWishlist($wishlist)
{
$this->wishlist = $wishlist;
return $this;
}
/**
* Get wishlist
*
* @return boolean
*/
public function getWishlist()
{
return $this->wishlist;
}
/**
* Set events
*
* @param boolean $events
*
* @return Roles
*/
public function setEvents($events)
{
$this->events = $events;
return $this;
}
/**
* Get events
*
* @return boolean
*/
public function getEvents()
{
return $this->events;
}
/**
* Set reports
*
* @param boolean $reports
*
* @return Roles
*/
public function setReports($reports)
{
$this->reports = $reports;
return $this;
}
/**
* Get reports
*
* @return boolean
*/
public function getReports()
{
return $this->reports;
}
/**
* Get roleid
*
* @return integer
*/
public function getRoleid()
{
return $this->roleid;
}
}
这个通过注册表单处理用户输入的控制器:
<?php
namespace Vendor\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Vendor\MyBundle\Entity\Logins;
use Vendor\MyBundle\Form\UserType;
use Vendor\MyBundle\Repository\LoginsRepository;
class MainController extends Controller
{
/**
* @Route("/", name="home_page")
*/
public function indexAction(Request $request)
{
// 1) build the form
$user = new Logins();
$form = $this->createForm(UserType::class, $user);
// 2) handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// 3) Encode the password
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPassword());
$user->setPassword($password);
$user->setCreationtime();
// 4) save the User!
$em = $this->getDoctrine()->getManager();
$roleid = $this->$em->getRepository('Vendor\MyBundle\Entity\Roles')->find(2); // or getReference
$user->setRoleid($roleid);
$em->persist($user);
$em->flush();
return $this->redirectToRoute('home_page');
}
return $this->render(
'VendorMyBundle:Default:index.html.twig',
array('form' => $form->createView())
);
}
简而言之,我的数据库中的角色 table 中有 2 条记录,具有主键 RoleID。 我希望当用户注册时,当我坚持并将数据刷新到数据库时,我在登录 Table 中的 RoleID 列 (FK) 默认填充值 2。
任何见解或替代方案都将受到赞赏。我在 Symfony 3.0.1 上。
我可以想到 2 种可能的解决方案来自动执行此操作。两者都使用 doctrine pre-persist event.
通过添加带有@ORM\PrePersist
注解的回调方法为实体添加pre-persist方法,并通过添加@ORM\HasLifecycleCallbacks
注解标记实体具有生命周期回调(read also here for more details on how to do this).
Here you can find Symfony specific documentation on the life cycle callback
/**
* @ORM\PrePersist
* @param \Doctrine\ORM\Event\LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
$entity= $args->getEntity();
if($entity->getRoleid() === null){
$entityManager = $args->getEntityManager();
$roleId = $entityManager->getReference(\Vendor\MyBundle\Entity\Roles::class, 2);
$entity->setRoleId($roleId);
}
}
注意:您也可以使用方法find
代替getReference
,但使用getReference
会节省您额外的往返时间到数据库。你说你有两个角色,如果你知道它们总是存在(固定装置),那么就没有必要解决它们。
但您也可以在外部侦听器(称为事件订阅者)中执行相同的操作。 Check here the Doctrine 2 documentation on this topic。
Here you can find Symfony specific documentation on the event subscriber。
namespace Vendor\MyBundle\Listener;
use Doctrine\ORM\Events;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Doctrine\Common\EventSubscriber;
class DefaultRoleListener implements EventSubscriber
{
/**
* @return array
*/
public function getSubscribedEvents()
{
return array(
Events::prePersist,
);
}
/**
* @param LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if( $entity instanceof Login) {
if($entity->getRoleid() === null){
$entityManager = $args->getEntityManager();
$roleId = $entityManager->getReference(\Vendor\MyBundle\Entity\Roles::class, 2);
$entity->setRoleId($roleId);
}
}
}
}
您需要附加您的侦听器(事件订阅者)。
$entityManager = // get your entity manager instance
$doctrineEventManager = $entityManager->getEventManager();
$defaultRoleListener = // get your listener instance
$doctrineEventManager->addEventSubscriber($defaultRoleListener);
但也许有一种 Symfony 方法可以做到这一点...我主要使用 Zend Framework。
两种解决方案的作用完全相同。这完全取决于您个人对逻辑存储位置的偏好;在您的实体中或在单独的侦听器中。
更新
如果你有问题让它工作,请确保你首先删除 \Vendor\MyBundle\Resources\config\
中任何现有的 YML/XML 文件,因为这些可能导致 Doctrine 忽略你的 prePersist
方法。
我忘记了什么。对于第一个解决方案,您还需要标记该实体具有生命周期回调。您可以通过添加注释 @HasLifecycleCallbacks
来完成此操作。并检查您是否在该方法上添加了 @PrePersist
。根据您的设置,您有时需要使用 @ORM\HasLifecycleCallbacks
或 @ORM\PrePersist
。你应该喜欢你的其他 @Entity
注释。
不确定为什么您收到评论中提到的错误消息。但是你可以反其道而行之,将我在回答中写的行换成你的控制器代码中的行,如果它们对你有用...