Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 3 - how to inject the validator into a service?

I try to inject the validator into my service - but I don't find it:

mybundle.service.supplier:
     class: AppBundle\Service\SupplierService
     calls:
        - [setValidator, ['@validator']]

the @validator is not the expected RecursiveValidator http://api.symfony.com/3.1/Symfony/Component/Validator/Validator/RecursiveValidator.html - the @validator is an interface.

So how can I inject the validator into my service?

This is what I want:

<?php

namespace AppBundle\Service;


use AppBundle\Entity\Supplier;
use AppBundle\Helper\EntityManagerTrait;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\Validator\RecursiveValidator;

/**
 * Class SupplierService
 * @package AppBundle\Service
 */
class SupplierService
{
    use EntityManagerTrait;

   /** @var RecursiveValidator $validator */
    protected $validator;

    /**
     * @return RecursiveValidator
     */
    public function getValidator()
    {
        return $this->validator;
    }

    /**
     * @param RecursiveValidator $validator
     * @return SupplierService
     */
    public function setValidator($validator)
    {
        $this->validator = $validator;

        return $this;
    }


    public function addSupplier($data)
    {
        $supplier = new Supplier();
        $validator = $this->getValidator();
        $errors = $validator->validate($supplier);

    }
}
like image 362
goldlife Avatar asked Oct 19 '16 12:10

goldlife


2 Answers

@validator is an interface.

This does not make sense. If it would be an interface, there could not be an instacne of Validator service. Yes, it does implement ValidatorInterface, but it is not it.

On the other hand, I am sure you would get an instance of RecursiveValidator. See my analyses:

  • Check the validator definition in Symfony's XML:

    <service id="validator" class="Symfony\Component\Validator\Validator\ValidatorInterface">
        <factory service="validator.builder" method="getValidator" />
    </service>
    
  • Check the definition of validator.builder factory service:

    <service id="validator.builder" class="Symfony\Component\Validator\ValidatorBuilderInterface">
        <factory class="Symfony\Component\Validator\Validation" method="createValidatorBuilder" />
        <call method="setConstraintValidatorFactory">
            <argument type="service" id="validator.validator_factory" />
        </call>
        <call method="setTranslator">
            <argument type="service" id="translator" />
        </call>
        <call method="setTranslationDomain">
            <argument>%validator.translation_domain%</argument>
        </call>
    </service>
    
  • Check the factory Symfony\Component\Validator\Validation::createValidatorBuilder. It returns an instance of ValidatorBuilder

  • Finally, check the ValidatorBuilder::getValidator(). It ends with the following:

    return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers);
    

So, you will get the correct instance (RecursiveValidator).

Hope this helps...

like image 81
Jovan Perovic Avatar answered Nov 06 '22 03:11

Jovan Perovic


In symfony 3.4 simply like this worked:

Config:

stl.transaction.import.writer.insurance_company:
        class: STL\TransactionBundle\Import\Writer\InsuranceCompanyWriter
        public: false
        arguments:
            - '@validator'

Your service:

use Symfony\Component\Validator\Validator\ValidatorInterface;
// ...
public function __construct(
        ValidatorInterface $validator,
    ) {
        $this->validator = $validator;
    }
like image 2
Darius.V Avatar answered Nov 06 '22 04:11

Darius.V