I\'ve set up a structure using Abstract classes for Forms, Fieldsets and InputFilters. Forms and Fieldsets have Factories while InputFilters are created and set on the Field
$fieldset->setInputFilter($inputFilter);
Assuming that $fieldset
is an instance of Zend\Form\Fieldset
, the method doesn't exist. This is because you need to set the input filter on the form (Zend\Form\Form)
.
If I was to modify your code I would do so in the following way. Modify the CountryForm
to provide the input filter via the form. This can be done without needing to define a custom input filter for each form, by using the Zend\InputFilter\InputFilterProviderInterface
and referencing your custom input filter under the type
key.
When the form element manager creates the form, it will also inject the input filter manager which will be able to find the custom CountryInputFilter
.
For example:
use Zend\InputFilter\InputFilterProviderInterface;
class CountryForm extends AbstractForm implements InputFilterProviderInterface
{
public function init()
{
//.. add the country fieldset here
}
/**
* getInputFilterSpecification
*
* Return the form's input filter specification array.
*
* @return array
*/
public function getInputFilterSpecification()
{
return [
// Refers to the country element (happens to be a fieldset)
'country' => [
// Tell the input filter factory what type of input filter.
'type' => 'Country\\InputFilter\\CountryInputFilter',
// You could even overload/change the default defined in the input filter
// here. This is useful as sometimes the requirements of the FORM are
// different from what the FIELDSET expects.
// [
// 'name' => 'name',
// 'required' => false,
// 'allow_empty' => true,
// ],
],
];
}
}
Since you've got all the classes set up already there is another approach (from @AlexP), by constructing and adding the InputFilters of the Fieldsets to the Forms InputFilter. Instead of using the InputFilterSpecifications.
So add the input filters to your input_filters
config key:
'form_elements' => [
'factories' => [
CountryForm::class => CountryFormFactory::class,
CountryFieldset::class => CountryFieldsetFactory::class,
],
],
'input_filters' => [
'factories' => [
CountryInputFilter::class => CountryInputFilterFactory::class,
CountryFieldsetInputFilter::class => CountryFieldsetInputFilterFactory::class,
],
],
Factory classes:
class CountryInputFilterFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
$inputFilter = new CountryInputFilter(
$serviceLocator->get(CountryFieldsetInputFilter::class),
$serviceManager()->get('Doctrine\ORM\EntityManager'),
$serviceManager()->get('translator')
);
return $inputFilter;
}
}
class CountryFieldsetInputFilterFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
return new CountryFieldsetInputFilter(
$serviceManager()->get('Doctrine\ORM\EntityManager'),
$serviceManager()->get('translator')
);
}
}
class CountryFormFactory implements AbstractFormFactory
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
$form = new CountryForm($this->name, $this->options);
$form->setObjectManager($serviceManager->get('Doctrine\ORM\EntityManager'));
$form->setTranslator($serviceManager->get('translator'));
$form->setInputFilter($serviceManager->get('InputFilterManager')->get(CountryInputFilterFactory::class));
return $form;
}
}
Form:
class CountryForm extends AbstractForm
{
const COUNTRY_FIELDSET_NAME = 'country';
// This one added for SO, does nothing but call parent#__construct, which would happen anyway
public function __construct($name = null, array $options)
{
parent::__construct($name, $options);
}
public function init()
{
//Call parent initializer.
parent::init();
$this->add([
'name' => self::COUNTRY_FIELDSET_NAME,
'type' => CountryFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
}
}
InputFilters:
class CountryInputFilter extends AbstractInputFilter
{
/** @var CountryFieldsetInputFilter */
protected $countryFieldsetInputFilter;
public function __construct(CountryFieldsetInputFilter $filter, $objectManager, $translator)
{
$this->countryFieldsetInputFilter = $filter;
// other dependencies
}
public function init()
{
$this->add($this->countryFieldsetInputFilter, CountryForm::COUNTRY_FIELDSET_NAME);
}
}
class CountryFieldsetInputFilter extends AbstractInputFilter
{
public function __construct($objectManager, $translator)
{
// dependencies
}
public function init()
{
$this->add([
// configuration
]);
}
}
Note that I injected the dependencies to the InputFilters per argument by instance instead of an array holding the instances.