2013-06-04 1 views
2

J'aimerais obtenir ServiceLocator dans ma classe de validation. J'ai essayé de l'obtenir à partir de l'instance de Controller mais elle renvoie null.Zend Framework 2: Comment obtenir ServiceLocator dans la classe de validation

MyValidation.php 
namespace Register\Validator; 

use Zend\Validator\AbstractValidator; 
use Register\Controller\RegisterController; 

class MyValidation extends AbstractValidator { 

    /* 
    code... 
    */ 

    function isValid($value) 
    { 
     $controller = new RegisterController(); 
     $sm = $controller->getServiceLocator(); 
     $tableGateway = $sm->get('Register\Model\RegisterTable'); 
     $tableGateway->myValidationMethod($value); 

    } 

}

module.php

public function getServiceConfig() 
{ 
    return array(
     'factories' => array(
      'Register\Model\RegisterTable' => function($sm) { 
       $tableGateway = $sm->get('RegisterTableGateway'); 
       $table = new RegisterTable($tableGateway); 
       return $table; 
      }, 
      'RegisterTableGateway' => function ($sm) { 
       $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); 
       $resultSetPrototype = new ResultSet(); 
       $resultSetPrototype->setArrayObjectPrototype(new RegisterUser()); 
       return new TableGateway('table-name', $dbAdapter, null, $resultSetPrototype); 
      }, 
     ), 
    ); 
} 

Mais je reçois Erreur fatale: Appel à une fonction membre get() sur un non-objet
Qu'est-ce qu'une bonne façon obtenir ServiceLocator dans la classe du modèle?

Répondre

7

Vous devez injecter les dépendances du validateur dans le validateur. Vous pouvez le faire via le tableau d'options lorsque vous affectez le validateur à un champ de formulaire. J'ai écrit quelques exemples de code pour montrer ce que je veux dire:

inscrire \ Validator \ MyValidation:

<?php 
namespace Application\Validator; 

use Zend\Validator\AbstractValidator; 

class MyValidation extends AbstractValidator 
{ 
    protected $tableGateway; 

    public function __construct($options = null) 
    { 
     parent::__constructor($options); 
     if ($options && is_array($options) && array_key_exists('tableGateway', $options)) 
     { 
      $this->tableGateway = $options['tableGateway']; 
     }   
    } 

    public function isValid($value) 
    { 
     // ... 
    } 
} 

En ce qui concerne la forme, vous pouvez soit mettre en œuvre le ServiceLocatorAwareInterface, il s'injecte automatiquement avec le localisateur de services , ou bien injectez des dépendances spécifiques dans le formulaire en utilisant une fabrique pour le formulaire.

Voilà comment vous le faire en utilisant le ServiceLocatorAwareInterface:

inscrire \ Form \ MonFormulaire:

<?php 
namespace Register\Form; 

use Zend\Form\Form; 
use Zend\InputFilter\InputFilterProviderInterface; 
use Zend\ServiceManager\ServiceLocatorAwareInterface; 

class MyForm extends Form implements InputFilterProviderInterface, ServiceLocatorAwareInterface 
{ 
    protected $servicelocator; 

    public function __construct() 
    { 
     $this->add(array(
       'name' => 'myfield', 
       'attributes' => array(
         'type' => 'text', 
       ), 
       'options' => array(
         'label' => 'Field 1' 
       ), 
      ) 
     ); 
    } 

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator) 
    { 
     $this->servicelocator = $serviceLocator; 
    } 

    public function getServiceLocator() 
    { 
     return $this->servicelocator; 
    } 

    public function getInputFilterSpecification() 
    { 
     return array(
      'myfield' => array(
       'required' => true, 
       'filters'  => array(), 
       'validators' => array(
         array(
          'name' => 'Application\Validator\MyValidator', 
          'options' => array(
           'tableGateway' => $this->getServiceLocator()->get('Application\Model\RegisterTable'), 
          ), 
         ), 
       ), 
      ), 
     ); 
    } 
} 

En outre, il est pas clair pour moi pourquoi vous instancier un contrôleur dans votre classe validateur. Tu ne devrais vraiment pas faire ça.

2

J'ai opté pour une approche différente. Au lieu de passer la dépendance du formulaire au validateur, je le passe du formulaire au ValidatorManager, qui est automatiquement injecté sur chaque validateur qui implémente l'interface ServiceLocatorAware.

<?php 

// Form 
public function getInputFilterSpecification(){ 
    $filter = new InputFilter(); 
    $factory = new InputFactory(); 

    // Inject SM into validator manager 
    $pm = $this->getServiceLocator()->get("ValidatorManager"); 

    $validatorChain = $factory->getDefaultValidatorChain(); 
    $validatorChain->setPluginManager($pm); 

    // Your validators here.. 
} 

// Validator 
class MyValidator extends AbstractValidator implements ServiceLocatorAwareInterface { 

    /** 
    * SM 
    * @var ServiceLocatorInterface 
    */ 
    private $serviceLocator; 

    /** 
    * Validate 
    */ 
    public function isValid($email){ 

     // Get the application config 
     $config = $this->getServiceLocator()->getServiceLocator()->get("config"); 

    } 

    /** 
    * ServiceLocatorAwarr method 
    * @param ServiceLocatorInterface $serviceLocator 
    * @return \Application\Module 
    */ 
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator){ 
     $this->serviceLocator = $serviceLocator; 
     return $this; 
    } 

    /** 
    * ServiceLocatorAwarr method 
    * @return ServiceLocatorInterface 
    */ 
    public function getServiceLocator(){ 
     return $this->serviceLocator; 
    } 
}