我现在已经在我的几个实体中遇到了这个问题,所以我想尝试了解真正发生的事情,然后我在这里求助于我最好的来源(一旦它符合条件,就会为这个问题添加一个赏金)。
我的用户是用户组的一部分。我有一个 userGroup 实体的验证器,以确保没有两个 userGroup 具有相同的名称。
问题是,当我去编辑一个用户并尝试为该用户选择该用户组时,symfony2 的行为就像我试图创建另一个具有相同名称的用户组,而实际上我所做的只是我在尝试为用户选择该用户组。
用户实体
<?php
// src/BizTV/UserBundle/Entity/User.php
namespace BizTV\UserBundle\Entity;
use BizTV\UserBundle\Validator\Constraints as BizTVAssert;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use BizTV\BackendBundle\Entity\company as company;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser implements AdvancedUserInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
//TODO: Add constraint on $name * @BizTVAssert\NameExists (and finish coding this constraint)
/**
* @var object BizTV\BackendBundle\Entity\company
*
* @ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* @ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* @var object BizTV\UserBundle\Entity\UserGroup
* @ORM\ManyToOne(targetEntity="BizTV\UserBundle\Entity\UserGroup")
* @ORM\JoinColumn(name="userGroup", referencedColumnName="id", nullable=true)
*/
protected $userGroup;
/**
* @ORM\ManyToMany(targetEntity="BizTV\ContainerManagementBundle\Entity\Container", inversedBy="users")
* @ORM\JoinTable(name="access")
*/
private $access;
/**
* @var object BizTV\ContainerManagementBundle\Entity\Container
*
* This only applies to the BizTV server user accounts or "screen display accounts". Others will have null here.
*
* @ORM\ManyToOne(targetEntity="BizTV\ContainerManagementBundle\Entity\Container")
* @ORM\JoinColumn(name="screen", referencedColumnName="id", nullable=true)
*/
protected $screen;
/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $isServer;
public function __construct()
{
parent::__construct();
$this->access = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set company
*
* @param BizTV\BackendBundle\Entity\company $company
*/
public function setCompany(\BizTV\BackendBundle\Entity\company $company)
{
$this->company = $company;
}
/**
* Get company
*
* @return BizTV\BackendBundle\Entity\company
*/
public function getCompany()
{
return $this->company;
}
/**
* Add access
*
* @param BizTV\ContainerManagementBundle\Entity\Container $access
*/
public function addContainer(\BizTV\ContainerManagementBundle\Entity\Container $access)
{
$this->access[] = $access;
}
/**
* Get access
*
* @return Doctrine\Common\Collections\Collection
*/
public function getAccess()
{
return $this->access;
}
/**
* Set screen
*
* @param BizTV\ContainerManagementBundle\Entity\Container $screen
*/
public function setScreen(\BizTV\ContainerManagementBundle\Entity\Container $screen)
{
$this->screen = $screen;
}
/**
* Get screen
*
* @return BizTV\ContainerManagementBundle\Entity\Container
*/
public function getScreen()
{
return $this->screen;
}
/**
* Set isServer
*
* @param boolean $isServer
*/
public function setIsServer($isServer)
{
$this->isServer = $isServer;
}
/**
* Get isServer
*
* @return boolean
*/
public function getIsServer()
{
return $this->isServer;
}
/**
* Set userGroup
*
* @param BizTV\UserBundle\Entity\UserGroup $userGroup
*/
public function setUserGroup(\BizTV\UserBundle\Entity\UserGroup $userGroup = null)
{
$this->userGroup = $userGroup;
}
/**
* Get userGroup
*
* @return BizTV\UserBundle\Entity\UserGroup
*/
public function getUserGroup()
{
return $this->userGroup;
}
}
用户链接到的 UserGroup 实体:
<?php
namespace BizTV\UserBundle\Entity;
use BizTV\UserBundle\Validator\Constraints as BizTVAssert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* BizTV\UserBundle\Entity\UserGroup
*
* @ORM\Table()
* @ORM\Entity
*/
class UserGroup
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string $name
* @BizTVAssert\NameExists
* @ORM\Column(name="name", type="string", length=255)
* @Assert\NotBlank(message = "Du måste ange ett gruppnamn")
*/
private $name;
/**
* @var object BizTV\BackendBundle\Entity\company
*
* @ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* @ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set company
*
* @param BizTV\BackendBundle\Entity\company $company
*/
public function setCompany(\BizTV\BackendBundle\Entity\company $company)
{
$this->company = $company;
}
/**
* Get company
*
* @return BizTV\BackendBundle\Entity\company
*/
public function getCompany()
{
return $this->company;
}
}
NameExistsValidator
<?php
namespace BizTV\UserBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Doctrine\ORM\EntityManager as EntityManager;
class NameExistsValidator extends ConstraintValidator
{
private $container;
private $em;
public function __construct(Container $container, EntityManager $em) {
$this->container = $container;
$this->em = $em;
}
public function isValid($value, Constraint $constraint)
{
$em = $this->em;
$container = $this->container;
$company = $this->container->get('security.context')->getToken()->getUser()->getCompany();
//Fetch entities with same name
$repository = $em->getRepository('BizTVUserBundle:UserGroup');
//$repository = $this->getDoctrine()->getRepository('BizTVContainerManagementBundle:Container');
$query = $repository->createQueryBuilder('c')
->where('c.company = :company')
->setParameter('company', $company)
->orderBy('c.name', 'ASC')
->getQuery();
$groups = $query->getResult();
foreach ($groups as $g) {
if ($g->getName() == $value) {
$this->setMessage('Namnet '.$value.' är upptaget, vänligen välj ett annat', array('%string%' => $value));
return false;
}
}
return true;
}
}
用户编辑表单
<?php
namespace BizTV\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormValidatorInterface;
use Symfony\Component\Form\FormError;
use Doctrine\ORM\EntityRepository;
class editUserType extends AbstractType
{
function __construct($company)
{
$this->company = $company;
}
public function buildForm(FormBuilder $builder, array $options)
{
$company = $this->company;
$builder
->add('locked', 'checkbox', array('label' => 'Kontot är låst, användaren kan inte logga in '))
->add('username', 'text', array('label' => 'Användarnamn '))
;
$builder
->add('userGroup', 'entity', array(
'label' => 'Användargrupp',
'empty_value' => 'Ingen grupptillhörighet',
'property' => 'name',
'class' => 'BizTV\UserBundle\Entity\UserGroup',
'query_builder' => function(\Doctrine\ORM\EntityRepository $er) use ($company) {
$qb = $er->createQueryBuilder('a');
$qb->where('a.company = :company');
$qb->setParameters( array('company' => $company) );
$qb->orderBy('a.name', 'ASC');
return $qb;
}
));
$builder
->add('email', 'email', array('label' => 'Epost '))
->add('plainPassword', 'repeated', array('type' => 'password', 'first_name' => 'Nytt lösenord ', 'second_name' => 'Upprepa lösenord ',));
$builder
->add('roles', 'choice', array(
'label' => 'Roller',
'expanded' => true,
'multiple' => true,
'choices' => array(
'ROLE_CONTENT' => 'Innehåll (Användaren kan lägga till, redigera och ta bort innehåll där du nedan beviljar åtkomst)',
'ROLE_LAYOUT' => 'Skärmlayout (Användaren kan skapa ny skärmlayout, redigera befintlig eller ta bort gällande skärmlayout där du nedan beviljar åtkomst)',
'ROLE_VIDEO' => 'Videouppladdning (Användaren har rätt att ladda upp videofiler till företagets mediabibliotek)',
'ROLE_ADMIN' => 'Administratör (Användaren är administratör med fulla rättigheter till allt precis som det konto du nu är inloggad på, var mycket restriktiv med att tilldela denna behörighet).',
),
))
;
$builder
->add('access', 'entity', array(
'label' => 'Behörigheter',
'multiple' => true, // Multiple selection allowed
'expanded' => true, // Render as checkboxes
'property' => 'select_label',
'class' => 'BizTV\ContainerManagementBundle\Entity\Container',
'query_builder' => function(\Doctrine\ORM\EntityRepository $er) use ($company) {
$qb = $er->createQueryBuilder('a');
$qb->innerJoin('a.containerType', 'ct');
$qb->where('a.containerType IN (:containers)', 'a.company = :company');
$qb->setParameters( array('containers' => array(1,2,3,4), 'company' => $company) );
$qb->orderBy('ct.id', 'ASC');
return $qb;
}
));
$builder-> addValidator(new CallbackValidator(function(FormInterface $form){
$email = $form->get('email')->getData();
if (empty( $email )) {
$form['email']->addError(new FormError("Du måste ange en epostadress för användaren"));
}
}));
$builder-> addValidator(new CallbackValidator(function(FormInterface $form){
$username = $form->get('username')->getData();
if (strpos($username,'#') !== false) {
$form['username']->addError(new FormError("Användarnamnet får inte innehålla tecknet #"));
}
}));
$builder-> addValidator(new CallbackValidator(function(FormInterface $form){
$username = $form->get('username')->getData();
if (empty($username)) {
$form['username']->addError(new FormError("Du måste ange ett namn för användaren"));
}
}));
//TODO check if username exists
}
public function getName()
{
return 'biztv_userbundle_newusertype';
}
}