Walidacja w Symfony2 – Custom Validation Constraint
Piszę właśnie aplikację do automatycznej obsługi rejestracji, zarządzania i płatności dla strony http://document-management.pl/ i napotkałem pewien problem z walidacją danych. Potrzebowałem sprawdzić w unikalność Stringa w dwóch różnych tabelach. Niestety Doctrine domyślnie tego nie obsługuje więc pośpieszyłem z napisaniem własnego walidatora. Dziarsko przeczytałem "How to create a Custom Validation Constraint", napisałem walidator i ... zonk
Fatal error: Class 'Symfony\Component\Validator\Constraints\UniqueDomain' not found in /home/kirkor/Projects/Beriko Software/document-management.pl/public_html_register/Symfony/vendor/symfony/src/Symfony/Component/Validator/Mapping/Loader/FileLoader.php on line 73
Szybki pogląd sytuacji. Utworzyłem 'Bundle' RegistrationBundle w przestrzeni nazw Beriko\DocMgm\RegistrationBundle. Układ katalogów:
/src
-Beriko
--DocMgm
----RegistrationBundle
-----Validation
------UniqueDomain.php
------UniqueDomainValidator.php
Mój plik /src/Beriko/DocMgm/RegistrationBundle/Resources/config/validation.yml:
Beriko\DocMgm\RegistrationBundle\Entity\CustomerForConfirmation:
properties:
name:
- NotBlank: ~
- MinLength: 3
surename:
- NotBlank: ~
- MinLength: 3
username:
- NotBlank: ~
- MinLength: 3
password:
- NotBlank: ~
- MinLength: { limit: 8 }
phone:
- NotBlank: ~
domain:
- NotBlank: ~
- MinLength: 1
- MaxLength: 50
- UniqueDomain: ~
Dla przykładu mój plik /src/Beriko/DocMgm/RegistrationBundle/Validation/UniqueDomain.php:
namespace Beriko\DocMgm\RegistrationBundle\Validation;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class UniqueDomain extends Constraint {
public $message = 'Podana domena jest już zajęta.';
public $em = null;
public function getRequiredOptions() {
return array();
}
public function validatedBy() {
return 'UniqueDomainValidator';
}
}
Oraz /src/Beriko/DocMgm/RegistrationBundle/Validation/UniqueDomainValidator.php:
namespace Beriko\DocMgm\RegistrationBundle\Validation;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\ConstraintValidator;
class UniqueDomainValidator extends ConstraintValidator {
/**
* @var RegistryInterface
*/
private $registry;
/**
* @param RegistryInterface $registry
*/
public function __construct(RegistryInterface $registry) {
$this -> registry = $registry;
}
/**
* @param string $domain
* @param Constraint $constraint
* @return bool
*/
public function isValid($domain, Constraint $constraint) {
// customer_for_confirmation.domain check
$em = $this -> registry -> getEntityManager($constraint -> em);
$repository = $em -> getRepository('RegistrationBundle:CustomerForConfirmation');
$result = $repository -> getCustomerByDomain($domain);
if (0 != count($result)) {
$this -> setMessage($constraint -> message);
return false;
}
// TODO: add customer.domain check
return true;
}
}
Jak widzicie ta klasa jeszcze nie jest skończona - brakuje jeszcze sprawdzenia drugiej tabeli.
I na koniec ostatni plik /src/Beriko/DocMgm/RegistrationBundle/Resources/config/services.yml:
parameters:
beriko.registration.validator.unique.domain.class: Beriko\DocMgm\RegistrationBundle\Validation\UniqueDomainValidator
beriko.registration.validator.unique.username.class: Beriko\DocMgm\RegistrationBundle\Validation\UniqueUsernameValidator
services:
beriko.registration.validator.unique.domain:
class: %beriko.registration.validator.unique.domain.class%
arguments: [@doctrine]
tags:
- { name: validator.constraint_validator, alias: UniqueDomainValidator }
beriko.registration.validator.unique.username:
class: %beriko.registration.validator.unique.username.class%
arguments: [@doctrine]
tags:
- { name: validator.constraint_validator, alias: UniqueUsernameValidator }
Należy pamiętać, że mój walidator działa jako serwis. Potrzebuje do działania wstrzyknąć Doctrine.
Pytanie brzmi - co w tym kodzie jest nie tak, że dostaję wyjątek?
Odpowiedź prosta:
- UniqueDomain: ~
zamień na
- Beriko\DocMgm\RegistrationBundle\Validation\UniqueDomain: ~
i pomyśleć, że straciłem na to tyle czasu...
Tags: doctrine, php, symfon2, symfony















