Validator's factory configuration can not overwrite the built-in Validator RecordExists::class

zend-validator
#1

Sorry for open another post to ask the same question!
I have been confused by this question for several weeks.

'validators' => [
    'factories' => [
        RecordExists::class => DbValidatorAbstractFactory::class,
        NoRecordExists::class => DbValidatorAbstractFactory::class,
    ],
],

the above configuration is useless, why?

It would not execute even I wrote “exit(‘hello factory!’);” in the DbValidatorAbstractFactory’s __construction function. It obvious not run into the factory logic.

===================================================

step 1. create a factory for the validator named DbValidatorAbstractFactory, it is beyond the module/Application/src/Validator/Factory folder.

 namespace Application\Validator\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\Db\RecordExists;

class DbValidatorAbstractFactory implements FactoryInterface
{

    private $options;

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        //exit('test whether it run this function'); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! nothing happened!!!
        if (isset($options['adapter'])) {
            return new $requestedName(ArrayUtils::merge(
                $options,
                ['adapter' => $container->get($options['adapter'])]
            ));
        }
        return new $requestedName($options);
    }

    public function setCreationOptions(array $options)
    {
        $this->options = $options;
    }
}

step 2 config the new validator factory in the module.config.php like:

'validators' => [
    'factories' => [
        RecordExists::class => DbValidatorAbstractFactory::class,
        NoRecordExists::class => DbValidatorAbstractFactory::class,
    ],
],

step 3 according the vendor\zendframework\zend-db\src\Adapter\AdapterServiceFactory.php, I made a customer dbadatper named ExpressAdapterServiceFactory in the folder module/Application/src/Db/Factory

namespace Application\Db\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class ExpressAdapterServiceFactory implements FactoryInterface
{

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $config = $container->get('config');
        return new Adapter($config['express']);
    }
}

step 4, My problem is step 4, I wanna to config this new customer db adatper in the top level global.php, how to config it? Can you teach me?

'service_manager' => [
    'factories' => [
        'adapter.express' => Application\Db\Factory\ExpressAdapterServiceFactory::class, //I dont think it is correct!
    ],
],

step 5, my Logistics.php model file is a combination of entity and inputfilter the same way as the official tutorial way as following:

namespace Application\Model\Main;

use Zend\Db\Adapter\AdapterInterface;
use Zend\Filter\StringToUpper;
use Zend\Filter\StringTrim;
use Zend\Filter\StripTags;
use Zend\Filter\ToFloat;
use Zend\Filter\ToInt;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Validator\Between;
use Zend\Validator\Db\NoRecordExists;
use Zend\Validator\Db\RecordExists;
use Zend\Validator\InArray;
use Zend\Validator\NotEmpty;
use Zend\Validator\Regex;
use Zend\Validator\StringLength;


class Logistics implements InputFilterAwareInterface
{
    public $id;
    public $customer; //customer need to check whether the input coustomerid is exist
    ...

    private $inputFilter;

    public function exchangeArray(array $data)
    {
        $this->id = !empty($data['id']) ? $data['id'] : null;
        $this->customer = !empty($data['customer']) ? $data['customer'] : null;
        ...
    }

    public function getArrayCopy()
    {
        return [
            'id' => $this->id,
            'customer' => $this->customer,
            ...
        ];
    }

    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new \DomainException(sprintf(
            '%s does not allow injection of an alternate input filter',
            __CLASS__
        ));
    }


    public function getInputFilter()
    {
        if ($this->inputFilter) return $this->inputFilter;

        $inputFilter = new InputFilter();

        $inputFilter->add([
            'name' => 'id',
            'required' => true,
            'filters' => [
                ['name' => ToInt::class],
            ],
        ]);

        $inputFilter->add([
            'name' => 'customer',
            'required' => true,
            'filters' => [
                ['name' => ToInt::class],
            ],
            'validators' => [
                [
                    'name' => RecordExists::class,
                    'options' => [
                        'table' => 'main_customers',
                        'field' => 'id',
                        'message' => 'customer id input is not exist in the customer table',
                        'adapter' => 'adapter.express',
                    ],
                ],
            ],
        ]);

        ....

        $this->inputFilter = $inputFilter;
        return $this->inputFilter;
    }
}
#2

Why do you open a new post for the same question? Please stay in the original post!

#3

@froschdesign

Sorry for that, nobody pay attention for the original one. :sob:

#4

You can write or ping me, but do not open a separate post with the same question. This confuses other users here in the forum.