Skip to content

Instantly share code, notes, and snippets.

@jmikola
Created June 14, 2010 22:28
Show Gist options
  • Save jmikola/438407 to your computer and use it in GitHub Desktop.
Save jmikola/438407 to your computer and use it in GitHub Desktop.
DoctrineOdmUnique Constraint for Symfony 2 Forms
<?php
public function registerAction()
{
$dm = $this->container->getDoctrine_Odm_DocumentManagerService();
Registration::setDocumentManager($dm);
$registration = new Registration();
$form = new RegistrationForm('registration', $registration);
if ($this->getRequest()->request->has('registration')) {
$form->bind($this->getRequest()->request->get('registration'));
if ($form->isValid()) {
$user = new User();
$user->setUsername($registration->username);
$dm->persist($user);
$dm->flush();
}
}
}
<?php
namespace Application\Validator\Constraints;
use Symfony\Components\Validator\Constraint;
class DoctrineOdmUnique extends Constraint
{
public $message = 'OpenSky.Validator.DoctrineOdmUnique.message';
public $documentManager;
public $className;
public $fieldName;
public $ignoreValues = array();
public function requiredOptions()
{
return array('documentManager', 'className', 'fieldName');
}
}
<?php
namespace Application\Validator\Constraints;
use Symfony\Components\Validator\Constraint;
use Symfony\Components\Validator\ConstraintValidator;
class DoctrineOdmUniqueValidator extends ConstraintValidator
{
public function isValid($value, Constraint $constraint)
{
if ($value === null) {
return true;
}
$query = $constraint->documentManager->createQuery($constraint->className)
->select($constraint->fieldName)
->whereIn($constraint->fieldName, (array) $value);
if (!empty($constraint->ignoreValues)) {
$query->whereNotIn($constraint->fieldName, (array) $constraint->ignoreValues);
}
if (count($query->execute())) {
$this->setMessage($constraint->message, array('value' => $value));
return false;
}
return true;
}
}
<?php
namespace Application\Form;
use Symfony\Components\Validator\Constraints;
use Symfony\Components\Validator\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\DocumentManager;
use Application\Validator\Constraints\DoctrineOdmUnique;
class Registration
{
protected static $documentManager;
public $username;
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata
->addPropertyConstraint('username', new Constraints\NotNull())
->addPropertyConstraint('username', new Constraints\NotBlank())
->addPropertyConstraint('username', new Constraints\MaxLength(255))
->addPropertyConstraint('username', new DoctrineOdmUnique(array(
'documentManager' => self::$documentManager,
'className' => 'Application\Entities\User',
'fieldName' => 'username',
)));
}
/**
* Initialize static reference to DocumentManager, since Constraints cannot
* access the container on their own.
*
* @param DocumentManager $documentManager
*/
public static function setDocumentManager(DocumentManager $documentManager) {
self::$documentManager = $documentManager;
}
}
@jmikola
Copy link
Author

jmikola commented Jun 14, 2010

We ran into problems using named Constraint groups (beyond the implied names derived from parent classes), so the solution was to create parameter-holding objects for binding to forms, with their own simple constraints. A custom constraint was created to perform uniqueness checks.

This was written for Doctrine ODM (used with MongoDB), but should port over to ORM fairly easily (with some changes to the Query methods). Also, since Constraints don't have access to the dependency injection container, a reference to the document manager is hackishly passed in as a static variable.

loadValidatorMetadata() is utlized by StaticMethodLoader, which is in the ClassMetadataFactory loader chain and used to construct the Form's Validator object.

See: http://gist.github.com/413724

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment