Symfony3 — Как добавить значения по умолчанию или сохранить значения по умолчанию в свойстве, являющемся свойством отношения «многие к одному»

У меня есть 2 сущности, которые связаны через отношение «многие к одному».
Когда я сохраняю / сохраняю значения в пользовательском вводе, перед фактическим сохранением у меня есть одно из свойств, которые пользователь не заполняет / не вводит, и я хочу установить его с помощью кода.

Итак, у меня есть логины:

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

Короче говоря, у меня есть 2 записи в таблице ролей в моей БД с первичным ключом RoleID.
Я хочу, чтобы, когда пользователь регистрировался, когда я сохранял и сбрасывал данные в БД, у меня был столбец RoleID (FK) в таблице логинов, заполненный значением 2 по умолчанию.

Любое понимание или альтернативы приветствуются. Я на Symfony 3.0.1.

3

Решение

Я могу придумать 2 возможных решения, чтобы сделать это автоматически. Оба используют Доктрина до-персистского события.

Добавьте метод pre-persist к объекту, добавив метод обратного вызова с @ORM\PrePersist аннотации и отметьте, что у объекта есть обратные вызовы жизненного цикла, добавив @ORM\HasLifecycleCallbacks аннотация (Читайте также здесь для более подробной информации о том, как это сделать).
Здесь вы можете найти специальную документацию Symfony по обратному вызову жизненного цикла

/**
* @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 сэкономит вам дополнительный туда-обратно в базу данных. Вы сказали, что у вас есть две роли, и если вы знаете, что они всегда есть (расписание), нет необходимости решать их.


Но вы также можете сделать то же самое во внешнем слушателе (называемом подписчиком событий). Посмотрите здесь документацию Doctrine 2 по этой теме..
Здесь вы можете найти специальную документацию Symfony для подписчика на событие..

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.

Оба решения будут делать то же самое. Все зависит от ваших личных предпочтений о том, где хранить логику; в вашей сущности или в отдельном слушателе.

ОБНОВИТЬ

Если у вас есть проблемы, чтобы заставить его работать, убедитесь, что вы сначала удалили все существующие файлы YML / XML в \Vendor\MyBundle\Resources\config\, поскольку те могут заставить Учение игнорировать ваши prePersist методы.

Я кое-что забыл. Для первого решения вам также нужно отметить, что у объекта есть обратные вызовы жизненного цикла. Вы делаете это, добавляя аннотацию @HasLifecycleCallbacks, И убедитесь, что вы добавили @PrePersist по методу. В зависимости от вашей настройки вам иногда нужно использовать @ORM\HasLifecycleCallbacks или же @ORM\PrePersist, Вы должны делать то же самое с другим @Entity аннотаций.

Не уверен, почему вы получили сообщение об ошибке, указанное в вашем комментарии. Но вы можете сделать обратное и обменять строки, которые я написал в своем ответе, на строки из кода вашего контроллера, если они работают на вас …

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]