Silex/Symfony表单验证器:确保值是唯一的


Silex/Symfony Form validator : ensure a value is unique

我将Silex与Form和Validator提供程序一起使用。

我有一个非常简单的注册表格:

  • 用户名
  • 密码
  • 密码确认

用户名必须是唯一的,如何检查?

这是我的代码:

$form = $app['form.factory']->createBuilder('form')
      ->add('username', 'text', array(
        'constraints' => array(
          new Assert'NotBlank(),
          new Assert'Length(array('min' => 6, 'max' => 20)))
        ))
      ->add('password', 'repeated', array(
        'constraints' => array(
          new Assert'NotBlank(),
          new Assert'Length(array('min' => 6, 'max' => 20))
          )
        ))
      ->getForm();

对于Symfony,我知道存在UniqueEntity约束,但它附带了Doctrine,我只使用Doctrine DBAL(Silex提供商)

我想我可以使用Callback约束,但我想知道是否有比用SQL查询编写回调更好的解决方案。。。或者编写我自己的约束对象

感谢

好的,我决定创建自己的Constraint,因为我可以在电子邮件中重用它。所以,这就是我的实现:

UniqueEntry.php:

<?php
/**
 * Ensure a value is unique in the database
 *
 * @author Thomas KELLER
 */
use Symfony'Component'Validator'Constraint;
use Symfony'Component'Validator'Exception'MissingOptionsException;
use Symfony'Component'Validator'Exception'InvalidArgumentException;
/**
 * @Annotation
 */
class UniqueEntry extends Constraint {
  public $notUniqueMessage = 'This value already exist in the database';
  public $dbal_connection;
  public $table;
  public $field;
  public function __construct($options = null)
  {
    parent::__construct($options);
    if ($this->dbal_connection === null)
      throw new MissingOptionsException(sprintf('The option "dbal_connection" is mandatory for constraint %s', __CLASS__), array('dbal_connection'));
    if (!$this->dbal_connection instanceof 'Doctrine'DBAL'Connection)
      throw new InvalidArgumentException(sprintf('The option "dbal_connection" must be an instance of Doctrine'DBAL'Connection for constraint %s', __CLASS__));
    if ($this->table === null)
      throw new MissingOptionsException(sprintf('The option "table" is mandatory for constraint %s', __CLASS__), array('table'));
    if (!is_string($this->table) OR $this->table == '')
      throw new InvalidArgumentException(sprintf('The option "table" must be a valid string for constraint %s', __CLASS__));
    if ($this->field === null)
      throw new MissingOptionsException(sprintf('The option "field" is mandatory for constraint %s', __CLASS__), array('field'));
    if (!is_string($this->field) OR $this->field == '')
      throw new InvalidArgumentException(sprintf('The option "field" must be a valid string for constraint %s', __CLASS__));
  }
}

UniqueEntryValidator.php:

<?php
use Symfony'Component'Validator'Constraint;
use Symfony'Component'Validator'ConstraintValidator;
class UniqueEntryValidator extends ConstraintValidator
{
  public function validate($value, Constraint $constraint)
  {
    $query = sprintf('SELECT `%s` FROM `%s` WHERE `%s` = ?',
      $constraint->field,
      $constraint->table,
      $constraint->field);
    $stmt = $constraint->dbal_connection->executeQuery($query, array($value));
    if ($stmt->fetch())
      $this->context->addViolation($constraint->notUniqueMessage);
  }
}

我发布我的实施有建议,所以请随意评论;)