2012-11-20 17 views
9

Próbuję utworzyć formularz rejestracji użytkownika, który sprawdza złożoność pola hasła. Napisałem niestandardowy weryfikator, aby to zrobić zgodnie z documentation. Ten plik znajduje się w moim module "User" w User \ src \ User \ Validator.Zend Framework 2 Custom Validators for Forms

<?php 

namespace User\Validator; 

use Zend\Validator\AbstractValidator; 

class PasswordStrength extends AbstractValidator { 

const LENGTH = 'length'; 
const UPPER = 'upper'; 
const LOWER = 'lower'; 
const DIGIT = 'digit'; 

protected $messageTemplates = array(
    self::LENGTH => "'%value%' must be at least 6 characters long", 
    self::UPPER => "'%value% must contain at least one uppercase letter", 
    self::LOWER => "'%value% must contain at least one lowercase letter", 
    self::DIGIT => "'%value% must contain at least one digit letter" 
); 

public function isValid($value) { 
    ... validation code ... 
} 
} 

Mój problem pojawia się podczas próby użycia tego walidatora w moim formularzu rejestracyjnym użytkownika. Próbowałem dodać walidatora do ServiceManager, konfigurując go w Module.php.

public function getServiceConfig() { 
    return array(
     'invokables' => array(
      'PasswordStrengthValidator' => 'User\Validator\PasswordStrength' 
     ), 
    ); 
} 

Następnie dodałem go do filtra wejściowego w User.php.

public function getInputFilter() { 
    if (!$this->inputFilter) { 
     $inputFilter = new InputFilter(); 
     $factory  = new InputFactory(); 

     $inputFilter->add($factory->createInput(array(
      'name'  => 'username', 
      'required' => true, 
      'validators' => array(
       array(
        'name' => 'StringLength', 
        'options' => array(
         'encoding' => 'UTF-8', 
         'min'  => 1, 
         'max'  => 100, 
        ), 
       ), 
      ), 
     ))); 

     $inputFilter->add($factory->createInput(array(
      'name'  => 'password', 
      'required' => true, 
      'validators' => array(
       array(
        'name' => 'PasswordStrengthValidator', 
       ), 
      ), 
     ))); 

     $this->inputFilter = $inputFilter; 
    } 

    return $this->inputFilter; 
} 

Jednak po uzyskaniu dostępu do formularza i naciśnięciu przycisku wysyłania otrzymuję wyjątek ServiceNotFoundException.

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for PasswordStrengthValidator 

Czy występuje problem z moją konfiguracją ServiceManager? Nie jestem nawet pewien, czy jest to odpowiedni sposób na użycie niestandardowego walidatora. Znalazłem wiele przykładów przy użyciu ZF1, ale dokumentacja i przykłady dla ZF2, które znalazłem, nie wykraczają poza pisanie walidatora, aby zaadresować jego integrację z formularzami itp. Każda rada byłaby bardzo doceniana.

Odpowiedz

3

"Weryfikator" nazwy krótkiej "ładujący, którego próbujesz użyć w swoim przykładzie, działa tylko wtedy, gdy najpierw zarejestrujesz tę krótką nazwę/alias za pomocą menedżera wtyczki walidatora (Zend\Validator\ValidatorPluginManager).

Jedną z alternatyw dla tego (i sposobu, w jaki to robię) jest wstrzykiwanie wystąpień niezbędnych niestandardowych weryfikatorów podczas tworzenia obiektu filtru formularza. To jest droga ZfcUser robi:

// Service factory definition from Module::getServiceConfig 
'zfcuser_register_form' => function ($sm) { 
    $options = $sm->get('zfcuser_module_options'); 
    $form = new Form\Register(null, $options); 
    $form->setInputFilter(new Form\RegisterFilter(
     new Validator\NoRecordExists(array(
      'mapper' => $sm->get('zfcuser_user_mapper'), 
      'key' => 'email' 
     )), 
     new Validator\NoRecordExists(array(
      'mapper' => $sm->get('zfcuser_user_mapper'), 
      'key' => 'username' 
     )), 
     $options 
    )); 
    return $form; 
}, 

Źródło: https://github.com/ZF-Commons/ZfcUser/blob/master/Module.php#L100

Tutaj, dwa ZfcUser\Validator\NoRecordExists przypadki Validator (jeden na e-mail i jeden dla nazwy użytkownika) są wstrzykiwane do konstruktora obiektu filtr wejściowy dla formularz rejestracyjny (ZfcUser\Form\RegisterFilter).

Następnie wewnątrz klasy ZfcUser\Form\RegisterFilter, poprawności, są dodawane do definicji elementów:

$this->add(array(
    'name'  => 'email', 
    'required' => true, 
    'validators' => array(
     array(
      'name' => 'EmailAddress' 
     ), 
     // Constructor argument containing instance of the validator 
     $emailValidator 
    ), 
)); 

Źródło: https://github.com/ZF-Commons/ZfcUser/blob/master/src/ZfcUser/Form/RegisterFilter.php#L37

wierzę Inną alternatywą jest wykorzystanie w pełni kwalifikowaną nazwę klasy jako weryfikatora name (np. "User \ Validator \ PasswordStrength" zamiast tylko "PasswordStrengthValidator"), chociaż nigdy nie próbowałem tego samodzielnie.

+0

Huh, nie zdawałem sobie sprawy, że może mieć do czynienia z nazwą byłem zarejestrowanie go jako ... I rzeczywiście wypróbowane ostatnią propozycję i skonfigurować go w ServiceManager z w pełni kwalifikowaną nazwą klasy i to wystarczy! Dzięki za pomoc! –

3

Usuń konfigurację, którą można wybrać do sprawdzenia.

i modyfikować ustawienia validatora do:

$inputFilter->add($factory->createInput(array(
      'name'  => 'password', 
      'required' => true, 
      'validators' => array(
       array(
        'name' => 'User\Validator\PasswordStrength', 
       ), 
      ), 
     ))); 

pracować dla mnie.

+0

Dzięki za odpowiedź. Wierzę, że to zadziała, ale usunięcie wymagającej konfiguracji oznacza, że ​​weryfikator nie zostanie zarejestrowany w ServiceManager. Jest to w porządku, ale zalecono mi, aby używać ServiceManager do takich zadań. –

5

można spróbować tego obejścia ... registrer swojej walidator w Module.php ale z funkcją getValidatorConfig lub w module.config.php pod klucz „Walidatory”.

public function getValidatorConfig() { 
    return array(
    'invokables' => array(
     'PasswordStrengthValidator' => 'User\Validator\PasswordStrength' 
    ), 
); 
} 

Następnie w User.php, spróbuj tego: (ale trzeba mieć dostęp do usług lokalizator można wstrzyknąć go z UserFactory itp)

$validatorManager = $this->getServiceLocator()->get('ValidatorManager'); 
// here you can test $validatorManager->get('PasswordStrengthValidator'); 

$validatorChain = new ValidatorChain(); 
$validatorChain->setPluginManager($validatorManager); 

$inputFilter = new InputFilter(); 
$inputFilter->getFactory()->setDefaultValidatorChain($validatorChain); 

Działa to dla mnie.

Martin

1

rozwiązanie Rufin działa jak czar. Etapy I następnie użyć niestandardowego walidator zostały (w moim przypadku, gdy weryfikator URL, aby sprawdzić, czy rzeczywiście istnieje web):

1) W module.config.php

'validators' => array(
    'invokables' => array(
     'UrlValidator' => 'Application\Validators\UrlValidator' 
    ), 
) 

2) na ścieżkę nakładania /src/Application/Validators/UrlValidator.php

namespace Application\Validators; 
use Zend\Validator\AbstractValidator;      
class UrlValidator extends AbstractValidator{ 
    const NOTURL = 'NOTURL'; 

    protected $messageTemplates = array(
     self::NOTURL => 'Value should be a valid URL', 
    ); 

    public function __construct(array $options = array()){ 
     parent::__construct($options); 
    } 

    public function isValid($value){ 
     $this->setValue($value);  
     if (!$this->validateurl($value)) { 
      $this->error(self::NOTURL); 
      return false; 
     } 
     return true; 
    } 
    private function validateurl($url) { 
     $ch = curl_init(); // initialize curl handle 
     curl_setopt($ch, CURLOPT_URL, $url); // set url to post to 
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($ch, CURLOPT_HEADER, 1); 
     $result = curl_exec($ch); 

     $info = curl_getinfo($ch); 
     $code = $info['http_code']; 
     curl_close($ch); 

     if ($code == substr($code, 0, 1) || substr($code, 0, 1) == '4' || substr($code, 0, 1) == '5') { 
      return false; 
     } else { 
      return true; 
     } 
    } 
} 

3) w postaci

$inputFilter->add($factory->createInput(array(
        'name' => 'url',      
        'validators' => array(
         array(
          'name' => 'NotEmpty', 
          'options' => array(
           'messages' => array(
            'isEmpty' => 'URL is required' 
           ) 
          ) 
         ), 
         array(
          'name'=>'Application\Validators\UrlValidator' 
         ) 
        ) 
     ))); 

Extr a) Jeśli chcesz go użyć w dowolnym miejscu aplikacji (np. wewnątrz kontrolera działania) można pobrać ze wtyczki ValidatorManager:

$urlValidator = $this->getServiceLocator()->get('ValidatorManager')->get('UrlValidator'); 
+0

Co zrobić, jeśli chcesz, aby faktyczny sprawdzian adresu URL (te zawinięcia) był obsługiwany przez metodę usługi? Jakikolwiek sposób wstrzyknąć usługę temu walidatorowi? Lub, jeśli nie, aby utworzyć instancję z walidatora? – Stephane

0

Tak, to może być invokable jak stwierdził Conti lub fabryki w przypadku trzeba wstrzyknąć Service Manager na przykład, albo Doctrine kierownika jednostki w następujący przykład. Jest to bardzo eleganckie rozwiązanie w ten sposób:

'validators' => array(
     'invokables' => array(
      //'emailExist' => 'Application\MyValidation\EmailExistValidator', 
     ), 
     'factories' => array(
      'emailExist' => function ($vm) { 
       $serviceLocator = $vm->getServiceLocator(); 
       $emailExistValidator = new \Application\MyValidation\EmailExistValidator(); 
       $doctrineEntityManager = $serviceLocator->get('Doctrine\ORM\EntityManager'); 
       $emailExistValidator->setObjectManager($doctrineEntityManager); 
       return $emailExistValidator; 
      }, 
     ), 
    ),