由于我正在扩展BaseUser,我的用户实体中没有属性$ name,如何向其添加验证,我可以向该实体添加属性$ username吗?是否会混淆或覆盖某些功能或验证或本机提供给用户类的?
我提出这个问题FOSUserBundle - Validation for username, password or email fields,但因为我使用了一堆对我不起作用的注释验证。
后续问题 - 我在fosUSerBundle XML文件中看到用于验证用户本身是一个使用截取用户名的检查器,我没有得到该功能,如果我有直接的SQL错误消息尝试添加与现有用户同名的用户。这是因为我使用注释会一起覆盖XML验证文件吗?
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;
所以我看了这里(symfony2 using validation groups in form)并在构建表单时将其添加到控制器中尝试了该解决方案,没有任何反应(仍然直接跳转到INSERT INTO SQL错误)
$entity = new User();
$request = $this->getRequest();
$form = $this->createForm(new newUserType($tempCompany), $entity, array('validation_groups'=>'registration'));
$form->bind($request);
我还试图在表单类中设置此validatino组“注册组”(这应该为您提供免费的“唯一用户和电子邮件验证”):
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => array('registration'),
));
}
仍然没有任何反应。保存时直接导致SQL错误...
答案 0 :(得分:3)
$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;
}
}
继承了唯一的usernameCanonical和emailCanonical验证,但它们位于验证组中。有关验证组here和here的更多信息。
到目前为止,我觉得FOSUserBundle使用的用户管理器就像是一个存储库,所以你会希望尽可能地使用它来与存储层进行交互。以下是控制器中的内容(同样,未经测试):
// 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()
));
我希望这会有所帮助。如果我能提供更多细节,请告诉我。我会在这里发布一些代码,但我的实现有点不同。
答案 1 :(得分:3)
您应该能够组合注释和PHP中定义的约束(但可能不是注释和XML中定义的约束)
<?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()
));
}
/* ... */
}
答案 2 :(得分:1)
这不是问题的答案,而是迄今为止的解决方案。我将验证器添加到我的表单(UserType)。
$validatorUsername = function(FormEvent $event){
$form = $event->getForm();
$myExtraField = $form->get('username')->getData();
if ( preg_match('/^[a-zA-Z0-9_]+$/',$myExtraField) == false ) {
$form['username']->addError(new FormError("Du får inte använda andra specialtecken än understreck (_)"));
}
};
答案 3 :(得分:1)
实现Symfony cookbook中记录的回调验证约束:http://symfony.com/doc/current/reference/constraints/Callback.html
示例:
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
);
}
答案 4 :(得分:0)
要更改$username
上的验证,我建议您采取FOSUserBundle - Change username validation中描述的步骤,这是最简单的方法。在单个项目中同时使用XML和Annotations没有任何问题。实际上建议不使用Annotations,因为它将映射元数据保留在实体/类之外,这是(Data)Mapper pattern的全部要点。
另一种方法是不扩展FOS\UserBundle\Model\User
,但实施FOS\UserBundle\Model\UserInterface
。您必须对UserProvider
和UserManager
进行一项小调整才能完成这项工作,它的描述为here。
接下来,您必须自己完成所有映射,您可以自由使用所需的任何注释。
至于验证$username
的唯一性,你应该注意两件事:
$username
翻译为$usernameCanonical
,并根据User
验证$usernameCanonical
实体是否唯一。这实际上是非常好的系统,因为您可以影响唯一性检查中使用的值。您甚至可以超越strtolower
(默认值),例如删除非单词字符,将é更改为e等等。因此,在检查$username
本身的唯一性时,实际上看不到任何值。< / LI>
醇>