0

Trying to create a custom validator, I need to use a service from its isValid method.

How to inject that service ?

As an alternative, I could try to instantiate the service from within the validator method, but the service constructor requires a controller object, which I don't have at that point.

Here is the validator:

class OrderNumber extends AbstractValidator
{
    const EXIST = 'exist';

    /**
     * @var array
     *
     */
    protected $messageTemplates = array();

    /**
     * @var element name
     *
     */
    private $element = null;


    /**
     * Options for this validator
     *
     * @var array
     */
    protected $options = array(
        'manager' => null,  // set entity manager to find if value already exist
    );

    /**
     * Constructor
     *
     * @param  array|Traversable|int $options OPTIONAL
     */
    public function __construct($options)
    {
        $this->messageTemplates = array(
            self::INVALID => \Application\Util\Translator::translate("This value is required"),
        );

        if (!isset($options['element']) || empty($options['element'])) {
          throw new \Exception('Element name is not difined');
        }

        $this->element = $options['element'];

        parent::__construct();
    }

    /**
     * Returns true if and only if no record where found in Autoself for the value.
     *
     * @param  string $value
     * @return bool
     */
    public function isValid($value, array $context = null) {
      $isAvailable = $vehiculeService->orderNumberIsAvailable($value);

      if ($vehiculeService->orderNumberIsAvailable($value)) {
        return true;
      } else {
        return false;
      }
    }
}
n00dl3
  • 21,213
  • 7
  • 66
  • 76
Stephane
  • 11,836
  • 25
  • 112
  • 175
  • You may have a look here [https://stackoverflow.com/questions/16926000/zend-framework-2-how-to-get-servicelocator-in-validation-class](https://stackoverflow.com/questions/16926000/zend-framework-2-how-to-get-servicelocator-in-validation-class). It is not a duplicate, but the approach seems very close to your needs – BenRoob Sep 28 '17 at 15:26
  • 1
    Saying: you should inject all your needed services while constructing your custom validator. – BenRoob Sep 28 '17 at 15:28

1 Answers1

0

I needed to pass the service manager in a validator for one of my projects. Confronted with the same problem as you, I decided to pass the service manager as a parameter in the options array. Here is may code :

public function __construct(array $options)
{
    $this->db_manager = $options['db_manager'];
    parent::__construct($options);
}

Here, db_manager is a service manager containing only what I need. As a matter of principle, I never get the full service manager.

This validator is then used in a form. To do this, in the class of the form I define a method getInputFilterSpecification containing the following array :

'recordSource' => [
            'name' => 'recordSource',
            'required' => true,
            'filters' => [
                [
                    'name' => 'StripTags'
                ],
                [
                    'name' => 'StringTrim'
                ],
                [
                    'name' => 'SbmPdf\Model\Filter\NomTable',
                    'options' => [
                        'db_manager' => $this->db_manager
                    ]
                ]
            ],
            'validators' => [
                [
                    'name' => 'SbmPdf\Model\Validator\RecordSource',
                    'options' => [
                        'db_manager' => $this->db_manager,
                        'auth_userId' => $this->auth_userId
                    ]
                ]
            ]
        ],

The form itself being built by a factory :

class DocumentPdfFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
    $db_manager = $serviceLocator->get('Sbm\DbManager');
    $pdf = $serviceLocator->get(Tcpdf::class);
    return new DocumentPdf($db_manager, ...);
}
Alain Pomirol
  • 828
  • 7
  • 14
  • One important bit for me was to inject the controller in the form constructor `public function __construct(VehiculeController $controller, ` so that the vehiculeService option could instantiate it ` `'options' => [ 'vehiculeService' => new \Application\Service\VehiculeService($controller), ]` – Stephane Sep 30 '17 at 15:03