Pragmatism in the real world

Simple way to add a filter to Zend-InputFilter

Using Zend-InputFilter is remarkably easy to use:

use Zend\InputFilter\Factory as InputFilterFactory;

// set up InputFilter
$specification = [
    'my_field' => [
        'required' => false,
        'filters' => [
            ['name' => 'StringTrim'],
        ],
    ],
];
$factory = new InputFilterFactory();
$inputFilter = $factory->createInputFilter($specification);

// use InputFilter on some data
$data['my_field] = 'Some string';
$inputFilter->setData($data);
if ($inputFilter->isValid()) {
    Return false;
}
return $inputFilter->getValues(); // my_field is now trimmed

How do you add your filter to it though?

This is the world’s most simple filter that does absolutely nothing: We’ll call it MyFilter and store it in App\Filter\MyFilter.php:

<?php
namespace App\Filter;

use Zend\Filter\AbstractFilter;

class ToString extends AbstractFilter
{
    public function filter($value)
    {
        // do something to value here
        return $value;
    }
}

Now you have a couple of choices:

Extend Zend\InputFilter\Factory

I needed to add my own filter in the least invasive way that I could and so I created App\InputFilter\Factory which extends Zend\InputFilter\Factory:

<?php
namespace App\InputFilter;

use App\Filter\MyFilter;
use Zend\InputFilter\Factory as BaseFactory;
use Zend\InputFilter\InputFilterPluginManager;
use Zend\ServiceManager\Factory\InvokableFactory;

class Factory extends BaseFactory
{
    /**
     * @param InputFilterPluginManager $inputFilterManager
     */
    public function __construct(InputFilterPluginManager $inputFilterManager = null)
    {
        parent::__construct($inputFilterManager);

        // register our own filters
        $filterPluginManager = $this->getDefaultFilterChain()->getPluginManager();
        $filterPluginManager->setFactory(MyFilter::class, InvokableFactory::class);
        $filterPluginManager->setAlias('MyFilter', MyFilter::class);
    }
}

This class extends the standard Factory class and registers our filter into the filter chain’s plugin manager. Note that we have to register the factory for the fully qualified filter classname and also we register an alias for the short form (‘MyFilter’) as that’s much nicer to use in the specification.

To use our new factory, we change the use statement to use our new factory:

use App\InputFilter\Factory as InputFilterFactory;

Now we can use 'MyFilter' in our specification:

$specification = [
    'my_field' => [
        'required' => false,
        'filters' => [
            ['name' => 'StringTrim'],
            ['name' => 'MyFilter'],
        ],
    ],
];

Update your container’s factory

If you’re already injecting the InputFilter‘s Factory to the class that’s specifying the InputFilter, then it’s easier to update that factory. For Pimple, this looks something like:

<?php
use App\Filter\MyFilter;
use Zend\InputFilter\Factory;
use Zend\ServiceManager\Factory\InvokableFactory;

$container['InputFilterFactory'] = function ($c) {
    $factory = new Factory();

    // register our own filters
    $filterPluginManager = $factory->getDefaultFilterChain()->getPluginManager();
    $filterPluginManager->setFactory(MyFilter::class, InvokableFactory::class);
    $filterPluginManager->setAlias('MyFilter', MyFilter::class);
    $inputFilter = $factory->createInputFilter($specification);

    return $factory;
};

We don’t need to change anything else and we can use 'MyFilter' in our specification:

$specification = [
    'my_field' => [
        'required' => false,
        'filters' => [
            ['name' => 'StringTrim'],
            ['name' => 'MyFilter'],
        ],
    ],
];

One thought on “Simple way to add a filter to Zend-InputFilter

Comments are closed.