symfony2:如何向用户名添加验证规则?
由于我正在扩展symfony2:如何向用户名添加验证规则?,symfony,validation,fosuserbundle,Symfony,Validation,Fosuserbundle,由于我正在扩展BaseUser,因此在我的用户实体中没有属性$name。如何向其添加验证?我是否可以将属性$username添加到此实体?这会干扰或覆盖某些功能或验证,或是本机提供给用户类的功能或验证吗 我问了这个问题:。 但是由于我使用了大量的注释验证,这对我来说是行不通的 后续问题-我在fosUSerBundleXML文件中看到了这一点,用于验证用户本机是否有一个用于使用已获取用户名的检查器。我没有这个功能,如果我尝试添加一个与现有用户同名的用户,我的会直接显示一条SQL错误消息。这是不是因
BaseUser
,因此在我的用户实体中没有属性$name
。如何向其添加验证?我是否可以将属性$username
添加到此实体?这会干扰或覆盖某些功能或验证,或是本机提供给用户类的功能或验证吗
我问了这个问题:。但是由于我使用了大量的注释验证,这对我来说是行不通的 后续问题-我在
fosUSerBundle
XML文件中看到了这一点,用于验证用户本机是否有一个用于使用已获取用户名的检查器。我没有这个功能,如果我尝试添加一个与现有用户同名的用户,我的会直接显示一条SQL错误消息。这是不是因为我使用的注释一起覆盖了XML验证文件
<?php
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;
class User extends BaseUser implements AdvancedUserInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
//TODO: Add regex on $name for a-z, A-Z, 0-9 and _ (underscore)
//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;
我还尝试通过以下方式将此验证组设置为“注册组”(即“免费”为您提供唯一的用户和电子邮件验证):
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('registration'),
));
}
还是什么都没发生。保存时直接返回SQL错误。这不是问题的答案,但到目前为止对我来说是一个解决方案。我将验证器添加到我的表单(UserType)
我提前道歉。我不完全确定您是想验证
$name
属性还是$username
属性,但我希望这能为您指明正确的方向
要添加带有正则表达式验证的$name
属性,它应该如下所示。未经测试,但我将从这里开始:
<?php
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string")
* @Assert\NotBlank(groups={"Registration","Profile"})
* @Assert\Regex(pattern="/^[a-zA-Z0-9_]+$/", groups={"Registration","Profile"})
*/
protected $name;
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
}
如果您使用的是表单生成器或捆绑包未提供的表单类型,则其外观可能如下所示:
// setting values from a form
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$form = $this->container->get('form.factory')
->createBuilder('form', $user, array('validation_groups' => 'Registration'))
->add('username', 'text')
->add('email', 'email')
->add('name', 'text')
->add('plainPassword', 'repeated', array(
'type' => 'password'
))
->getForm();
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$userManager->updateUser($user);
// redirect response
}
}
return $this->container->get('templating')->renderResponse($templateName, array(
'form' => $form->createView()
));
我希望这有帮助。如果我能提供更多细节,请告诉我。我想在这里发布一些代码,但我的实现有点不同。实现回调验证约束,该约束在Symfony cookbook中有记录: 例如:
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;
/**
* @Assert\Callback(methods={"validateName"})
*/
class User extends BaseUser implements AdvancedUserInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @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;
/**
* @param ExecutionContextInterface $context
*/
public function validateName(ExecutionContextInterface $context)
{
// do some validation
// or add violation
$context->addViolationAt(
'name',
'Name "%name% is not valid',
array('%name%' => $this->getName()),
null
);
}
要更改对
$username
的验证,我建议您执行中描述的步骤,这是最简单的方法。在单个项目中同时使用XML和注释没有什么错。实际上建议不要使用注释,因为它将映射元数据保留在实体/类之外,这是()的要点
另一种方法是不扩展FOS\UserBundle\Model\User
,而是实现FOS\UserBundle\Model\UserInterface
。下面介绍了您必须对UserProvider
和UserManager
进行一个小的调整,以使其正常工作。
接下来,您必须自己完成所有映射,您可以自由使用任何您想要的注释
至于验证$username
的唯一性,您应该注意两件事:
$username
转换为$usernamecononical
,并基于$usernamecononical
验证用户
实体是否唯一。这实际上是一个非常好的系统,因为您可以影响唯一性检查中使用的值。您甚至可以比strtolower更进一步(默认设置),例如删除非单词字符、将é更改为e等。因此,在检查$username
本身的唯一性时,实际上看不到任何值您应该能够组合在注释和PHP中定义的约束(但可能不能同时组合在注释和XML中定义的约束)
Nut检查其他同名用户需要数据库连接,我的印象是这样的查询不能(或至少不应该)从实体类内部运行?在Symfony 2.4中,您可以在外部类中设置这些回调验证。看医生:啊,误解你了。也许这就是你要找的?我不知道更好的解决方案现在我正在考虑验证用户名(虽然其他东西的regexp也很有趣。我自己对这个问题的答案(不是真正的答案)表明,我做了一些变通。但我不能继承这个所谓的“免费”的东西唯一用户名和emai…的功能是ORM用户验证。您将看到为验证组“注册”和“配置文件”设置了Symfony\Bridge\doctor\Validator\Constraints\uniquentity
,因此“注册”将不起作用。请尝试$userManager->updateUser($entity,false);var\u dump($entity);exit();
查看您的实体值。我不确定还可以尝试什么,因为您有很多不同的代码尝试执行相同的操作(例如表单中的验证程序事件侦听器)。我通常通过查看对象中的数据来解决这类问题,以确保所有内容都已正确设置。具体而言,UsernameCononical、emailCanonical、plainPassword、password等。我怀疑UsernameCononical字段未设置。请尝试调用$userManager->updateCanonicalFields($entity);
在验证之前。我想知道是否设置了UsernameCononical字段(否则验证将不起作用)。如果手动调用updateCanonicalFields,然后进行验证,我打赌它可以解决您的问题。
// setting values manually
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setName('Joe');
$user->setUsername('joeuser');
$user->setEmail('joe@gmail.com');
$user->setPlainPassword('secret');
$user->addRole('ROLE_EDITOR');
// persist to database
$userManager->updateUser($user);
// inherited validations that check for username and email uniqueness
// using validation group names 'Registration' and 'Profile'
$uniqueEmail = $user->getEmailCanonical();
$uniqueUsername = $user->getUsernameCanonical();
// setting values from a form
$userManager = $this->container->get('fos_user.user_manager');
$user = $userManager->createUser();
$form = $this->container->get('form.factory')
->createBuilder('form', $user, array('validation_groups' => 'Registration'))
->add('username', 'text')
->add('email', 'email')
->add('name', 'text')
->add('plainPassword', 'repeated', array(
'type' => 'password'
))
->getForm();
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$userManager->updateUser($user);
// redirect response
}
}
return $this->container->get('templating')->renderResponse($templateName, array(
'form' => $form->createView()
));
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;
/**
* @Assert\Callback(methods={"validateName"})
*/
class User extends BaseUser implements AdvancedUserInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @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;
/**
* @param ExecutionContextInterface $context
*/
public function validateName(ExecutionContextInterface $context)
{
// do some validation
// or add violation
$context->addViolationAt(
'name',
'Name "%name% is not valid',
array('%name%' => $this->getName()),
null
);
}
<?php
/* ... */
use Symfony\Component\Validator\Mapping\ClassMetadata;
class User extends BaseUser implements AdvancedUserInterface
{
/* ... */
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint(
'username'
, new Assert\Regex(array(
'pattern' => '/^[a-zA-Z0-9_]$/'
)
));
$metadata->addPropertyConstraint(
'username'
, new BizTVAssert\NameExists()
));
}
/* ... */
}