About zf3 validator of RecordExists

@froschdesign @Moln

Pls look at the above 5 steps I listed(I edited my reply and added the step 5), it is almost the whole logic for this part, pls help me out!

In fact, I took the above 5 steps and submit the form then I got a error when I use

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

Argument 1 passed to Zend\Validator\Db\AbstractDb::setAdapter() must be an instance of Zend\Db\Adapter\Adapter, string given, called in /opt/www/websites/somedomain.com/vendor/zendframework/zend-validator/src/AbstractValidator.php on line 139

It says that, it need a adatper instance, But I passed a string.

I guess the replacement of the default recordexist validator not happen, I can not overwrite the default RecordExists::class and NoRecordExists::class eighter I put the configuration in global.php or module.config.php, why?

I moved the following configs from module.config.php to global.php

'validators' => [
    'factories' => [
        Zend\Validator\Db\NoRecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
        Zend\Validator\Db\RecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
    ],
],

Iā€™m sorry, but it is hard to follow you here and what you may have forgotten or overlooked. Can you create a repository and provide the link?

@froschdesign

Now forget about the factory stuff, now my question concentrate on that I can not overwrite the built-in validator RecordExists when I use the following configuration in the module.config.php.

'validators' => [
    'factories' => [
        Zend\Validator\Db\NoRecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
        Zend\Validator\Db\RecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
    ],
],

The above configuration not work, because when I use RecordExists::class in the inputfilter, it calls the built-in validator, not the factory I registered with the above configuration.
I donā€™t know why.

Is zend-validator registered as module in application.config.php?

I have provided an example in this.

I think the class DbValidatorAbstractFactory merge to zend-validator will be better.

@froschdesign

No, my application.config.php is just the same as the one provided by @Moln

In the top level modules.config.php, the config as following(in this file, there is zend-validator ):

return [
    'Zend\Paginator',
    'Zend\ServiceManager\Di',
    'Zend\Session',
    'Zend\Mvc\Plugin\Prg',
    'Zend\Mvc\Plugin\Identity',
    'Zend\Mvc\Plugin\FlashMessenger',
    'Zend\Mvc\Plugin\FilePrg',
    'Zend\Mvc\I18n',
    'Zend\Log',
    'Zend\Form',
    'Zend\Db',
    'Zend\Cache',
    'Zend\Router',
    'Zend\Validator', //<==============do you mean this?
    'Application',
    'Old',
];

Right, but we must not forget the adapter Zend\Db\Adapter\AdapterInterface itself.

Hi @Moln
Thanks for your reply!

If all the inputfilter configed here, this file module.config.php will be very fat!! Generally, I hate to put the inputfilter config here.

What effects ?

Itā€™s compatible with AdapterInterface option.

[
  'name' => RecordExists::class,
  'options' => [
    'adapter' => Adapter\AdapterInterface::class, // It's work.
  ]
]
$dbAdapter = new \Zend\Db\Adapter\Adapter(...);

[
  'name' => RecordExists::class,
  'options' => [
    'adapter' => $dbAdapter,   // It's work, too.
  ]
]

@jobsfan
You do not need the input-filter implementation from @Moln. Ignore that. The important part is the factory for the db-validators.

@froschdesign

Do you have any idea about the problem I encountered? I can only list the above 5 steps with my poor english.

Now the problem is that the configuration which I wanna to overwrite the default built-in RecordExists validator is workless.

'validators' => [
    'factories' => [
        Zend\Validator\Db\NoRecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
        Zend\Validator\Db\RecordExists::class => Application\Validator\Factory\DbValidatorAbstractFactory::class,
    ],
],

I donā€™t know how to make it more clear for you to understand. The key code are contained in the above 5 steps I listed above.

You can split module.config.php file.

- config/
  - module.config.php
  - input_filters.config.php 

Another solution. Or create a class AlbumInputFilter instead and get it by InputFilterPluginManager service.

class AlbumInputFilter extends InputFilter {
  public function init() { // Not `__construct`
    $this->add(['name' => 'title']);
  }
}

class AlbumControllerFactory
{
    public function __invoke(ContainerInterface $container)
    {
        return new AlbumController(
            $container->get(AlbumTable::class),
            $container->get(InputFilterPluginManager::class)->get(AlbumInputFilter::class)
        );
    }
}

In module.config.php.

return [
    'input_filters' => [
        'factories' => [
            AlbumInputFilter::class => InvokableFactory::class,
        ],
    ],
];

Because of you can not direct new InputFilter().

If you want it to work, you need to get ValidatorPluginManager service in ServiceManager and inject
into $inputfilter.

$if = new InputFilter();

// Get `ValidatorPluginManager` service in `ServiceManager`
// It will inject 'validators' config.
$validators = $container->get(ValidatorPluginManager::class);

// Inject `$validators` into `$inputfilter`.
$if->getFactory()->getDefaultValidatorChain()->setPluginManager($validators); 
$if->add(...);
1 Like

Good catch! (I looked always on the first post. But later in a different code example [step 5.] the line with new InputFilter() is included.)

@froschdesign @Moln

It seems that why the validator configuration is useless that because I new the InputFilter() directly via the operater [new]?

The above method need to inject the dependency of the $container to the Album.php(because my getInputFilter is inside this file, I followed the official tutorial), I donā€™t think it is better than I set a setAdapter function to the entity model, @Moln, Remember you taught me a way to add a setAdapter method and set $this->adapter with an db adapter instance.
If I use this way, I need to add a setContainer function to get the instance of the $container from outside. and then following your way, it is a little more complicated than setAdapter way.

Except this method, pls check for me whether the following method work or not.

  class AlbumControllerFactory
 {
     public function __invoke(ContainerInterface $container)
    {
        $container->get(InputFilterPluginManager::class); //<===I do not need to get something, just to make the validator configuration work, is it ok?
        return new AlbumController(
            $container->get(AlbumTable::class),
            //$container->get(InputFilterPluginManager::class)->get(AlbumInputFilter::class) <====move this part to upward
        );
    }
}

@jobsfan
Is the input-filter only used in a form?