由于
@UniqueEntity(fields = "用户名"...
下面绝对什么都不做(可能是因为用户名是继承的,而不是我在用户类中明确定义的?)我想我将不得不做一些简单的事情,比如在控制器或表单验证中手动检查具有该名称的现有用户。所以我使用表单验证。
我不知道如何从表单类访问数据库,手动从表单类内部使用 queryBuilder。
这是我的表单类:
namespace BizTV\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;
use Doctrine\ORM\EntityRepository;
class editUserType extends AbstractType
{
function __construct($company)
{
$this->company = $company;
}
public function buildForm(FormBuilderInterface $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_losenord', 'second_name' => 'Upprepa_losenord',));
$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;
}
));
$validatorEmail = function(FormEvent $event){
$form = $event->getForm();
$myExtraField = $form->get('email')->getData();
if (empty($myExtraField)) {
$form['email']->addError(new FormError("Du måste ange en epostadress för användaren"));
}
};
$validatorUsername = function(FormEvent $event){
$form = $event->getForm();
$myExtraField = $form->get('username')->getData();
if (empty($myExtraField)) {
$form['username']->addError(new FormError("Du måste ange ett namn för användaren"));
}
elseif ( preg_match('/^[a-zA-Z0-9_]+$/',$myExtraField) == false ) {
$form['username']->addError(new FormError("Du får inte använda andra specialtecken än understreck (_)"));
}
};
$validatorUsernameTaken = function(FormEvent $event){
$form = $event->getForm();
$myExtraField = $form->get('username')->getData();
//TODO: CHECK IN DB FOR USER WITH THAT NAME
if ($taken) {
$form['username']->addError(new FormError("Du måste ange ett namn för användaren"));
}
};
// adding the validator to the FormBuilderInterface
$builder->addEventListener(FormEvents::POST_BIND, $validatorEmail);
$builder->addEventListener(FormEvents::POST_BIND, $validatorUsername);
$builder->addEventListener(FormEvents::POST_BIND, $validatorUsernameTaken);
//TODO check if username exists
}
public function getName()
{
return 'biztv_userbundle_newusertype';
}
}
顺便说一句,这是我的实体:
namespace BizTV\UserBundle\Entity;
use BizTV\UserBundle\Validator\Constraints as BizTVAssert;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use BizTV\BackendBundle\Entity\company as company;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
* @UniqueEntity(fields = "username", message = "En användare med det namnet finns redan, försök igen.")
*/
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;
}
//Below should be part of base user class but doesn't work so I implement it manually.
/**
* Get lock status
*
* @return boolean
*/
public function getLocked()
{
return $this->locked;
}
}
- - - 更新 - - -
我的控制器的更新用户方法:
public function createUserAction()
{
$tempCompany = $this->container->get('security.context')->getToken()->getUser()->getCompany()->getId();
$entity = new User();
$request = $this->getRequest();
$form = $this->createForm(new newUserType($tempCompany), $entity);
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$encoder = $this->container->get('security.encoder_factory')->getEncoder($user); //get encoder for hashing pwd later
//get company
$currentCompany = $this->container->get('security.context')->getToken()->getUser()->getCompany();
//Set company
$entity->setCompany( $currentCompany );
$tempUsername = $entity->getUsername();
$entity->setUsername($currentCompany->getCompanyName() . "-" . $tempUsername);
$entity->setConfirmationToken(null);
$entity->setEnabled(true);
$tempPassword = $encoder->encodePassword($entity->getPassword(), $entity->getSalt());
$entity->setPassword($tempPassword);
$em->persist($entity);
$em->flush();
$helper = $this->get('biztv.helper.globalHelper');
$helper->log('success', 'Användare <strong>'.$entity->getUsername().'</strong> har skapats.');
return $this->redirect($this->generateUrl('UserManagement'));
}
return $this->render('BizTVUserBundle:Default:newUser.html.twig', array(
'entity' => $entity,
'form' => $form->createView()
));
}
那么我做这一切都错了吗?我实际上是按照您的建议使用 userManager ,但仅用于对密码进行编码。我是否应该保留使用 $userManager 创建的 $user 而不是保留我自己的 $entity,这会让我利用唯一检查等吗?
- - - - - - 更新 - - - - - - - -
@jmickell(在这里发布答案,因为评论中没有代码格式,谢谢您的时间。但是我还没有解决方案......)
我根据this更改了代码
$em = $this->getDoctrine()->getManager();
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$encoder = $this->container->get('security.encoder_factory')->getEncoder($user); //get encoder for hashing pwd later
//get company
$currentCompany = $this->container->get('security.context')->getToken()->getUser()->getCompany();
//Set company
$entity->setCompany( $currentCompany );
$tempUsername = $entity->getUsername();
$entity->setUsername($currentCompany->getCompanyName() . "-" . $tempUsername);
$entity->setConfirmationToken(null);
$entity->setEnabled(true);
$tempPassword = $encoder->encodePassword($entity->getPassword(), $entity->getSalt());
$entity->setPassword($tempPassword);
$userManager->updateUser($entity);
它可以像您所说的那样在没有刷新的情况下保存用户,但是没有对用户名/密码进行验证。我想这是必须在此之上发生的事情,形式为 isValid?还是在表单类本身内部?
如果您看一下我的表单类(问题的最重要部分),我是否遗漏了一些必须让 usernameCanonical 和 emailCanonical 的验证器发挥作用的东西?
另外,如果我更换这个
$tempPassword = $encoder->encodePassword($entity->getPassword(), $entity->getSalt());
$entity->setPassword($tempPassword);
有了这个(据我所知你建议)
$entity->setPlainPassword( $entity->getPassword() );
我最终得到一个 SQL 错误,告诉我密码字段不能为空......
我也尝试过将验证组添加到这样的表单中,但行为完全没有变化
因此,我查看了此处(symfony2 在表单中使用验证组)并通过在构建表单时将其添加到控制器来尝试该解决方案,但没有任何反应(仍然直接跳转到 INSERT INTO SQL 错误)
$entity = new User();
$request = $this->getRequest();
$form = $this->createForm(new newUserType($tempCompany), $entity, array('validation_groups'=>'registration'));
$form->bind($request);
我还尝试以这种方式在表单类中设置此验证组“注册组”(应该“免费”为您提供唯一的用户和电子邮件验证):
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('registration'),
));
}