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…