Skip to content

Instantly share code, notes, and snippets.

@grizzm0
Last active August 9, 2021 14:13
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save grizzm0/c5ff73d8a8df7a4387fd to your computer and use it in GitHub Desktop.
Save grizzm0/c5ff73d8a8df7a4387fd to your computer and use it in GitHub Desktop.
Best practice form/input-filter setup for ZF3
<?php
namespace Application\Entity;
/**
* Class Foo
*
* @package Application\Entity
*/
class Foo
{
/**
* @var int
*/
protected $id;
/**
* @var string
*/
protected $email;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* @param string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
}
<?php
namespace Application\Form;
use Zend\Form\Element\Email;
use Zend\Form\Form;
/**
* Class FooForm
*
* @package Application\Form
*/
class FooForm extends Form
{
const EMAIL = 'email';
/**
* {@inheritdoc}
*/
public function init()
{
$this->add([
'name' => self::EMAIL,
'type' => Email::class,
'options' => [
'label' => self::EMAIL,
],
]);
}
}
<?php
namespace Application\Factory\Form;
use Application\Entity\Foo;
use Application\Form\FooForm;
use Application\InputFilter\FooInputFilter;
use Interop\Container\ContainerInterface;
use Zend\Stdlib\Hydrator\ClassMethods;
/**
* Class FooFormFactory
*
* @package Application\Factory\Form
*/
class FooFormFactory
{
/**
* {@inheritdoc}
*/
public function __invoke(ContainerInterface $container)
{
$form = new FooForm('foo');
$form->setHydrator($container->get('HydratorManager')->get(ClassMethods::class));
$form->setInputFilter($container->get('InputFilterManager')->get(FooInputFilter::class));
$form->setObject(new Foo());
return $form;
}
}
<?php
namespace Application\InputFilter;
use Application\Form\FooForm;
use Zend\Filter\StringToLower;
use Zend\Filter\StringTrim;
use Zend\InputFilter\InputFilter;
use Zend\Validator\EmailAddress;
/**
* Class FooInputFilter
*
* @package Application\InputFilter
*/
class FooInputFilter extends InputFilter
{
/**
* {@inheritdoc}
*/
public function init()
{
$this->add([
'name' => FooForm::EMAIL,
'required' => true,
'filters' => [
['name' => StringToLower::class],
['name' => StringTrim::class],
],
'validators' => [
['name' => EmailAddress::class],
],
]);
}
}
<?php
use Application\Factory\Form\FooFormFactory;
use Application\Form\FooForm;
use Application\InputFilter\FooInputFilter;
return [
'form_elements' => [
'factories' => [
FooForm::class => FooFormFactory::class,
],
],
'input_filters' => [
'factories' => [
FooInputFilter::class => Zend\ServiceManager\Factory\InvokableFactory::class,
],
],
];
@Saeven
Copy link

Saeven commented Feb 10, 2015

Thanks for the inspiration!

@willemserik
Copy link

willemserik commented Sep 16, 2017

hi, i followed this but it seems that my form is not picking up my input filter. do i need to do other things than described here to make it working? for example adding a target in my modules.config file maybe?

@CreativeNative
Copy link

For me it's also not working. Can't figure out why.

@grizzm0
Copy link
Author

grizzm0 commented Sep 28, 2017

@Bitworkz, @CreativeNative

You need to grab the form by using $serviceManager->get(FormElementManager::class)->get(FooForm::class) to get all the DI working. Simply using "new FooForm()" will generate a new instance of the ServiceManager without your custom config.

@bitwombat
Copy link

This is great grizzm0 - I find myself re-reading it often (and implementing parts... soon to be 100% and habit, I hope).

I didn't realise there was a 'HydratorManager' (unsurprisingly provided by zend-hydrator)!

What's the point of breaking out FooInputFilter rather than having FooForm implement InputFilterProviderInterface? SRP? Reuse. Does reuse happen in the wild much?

Considering zend-form's own elements use InputProviderInterface and just have the input spec right there in the class, I'm curious what the reason for deviating from this style is.

@CreativeNative
Copy link

CreativeNative commented Dec 11, 2017

In controller factory you have to use

$formManager = $container->get('FormElementManager');
$form = $formManager->get(FooForm::class);

@MartinB134
Copy link

Does this work without the Hydrator and is this also recommended for data that is not confidential? Also im interested in the answer for @bitwombats question.

Considering zend-form's own elements use InputProviderInterface and just have the input spec right there in the class, I'm curious what the reason for deviating from this style is.

:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment