Symfony3 - 如何在属性为多对一关系属性中添加默认值或保留默认值

时间:2016-02-02 20:10:28

标签: php entity-framework symfony doctrine-orm default-value

我有两个通过多对一关系相关的实体。 当我在用户输入上持久存储值时,在实际持久化之前,我有一个用户没有填充/提供输入的属性,我想通过代码设置它。

所以,我有登录实体:

<?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())
        );
    }

简而言之,我的数据库中的Roles表中有2条记录,主键为RoleID。 我希望当用户注册时,当我持久并将数据刷新到数据库时,我在登录表中的RoleID列(FK)默认填充值为2。

任何见解或替代方案都表示赞赏。我在Symfony 3.0.1上。

1 个答案:

答案 0 :(得分:1)

我可以想到两种可能的解决方案来自动执行此操作。两者都使用doctrine pre-persist event

通过添加带有@ORM\PrePersist注释的回调方法向实体添加预先持久化方法,并通过添加@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注释。

不确定为什么会收到评论中提到的错误消息。但你可以做相反的事情并交换我在你的答案中写的那些来自控制器代码的行,如果它们适合你...