I have two issues involving Zend\Form\Annotation\AnnotationBuilder.
First, I want to tell the AnnotationBuilder to create a Zend\Form\Fieldset rather than a Zend\Form\Form (because the docs say it's good practice to use fieldsets for your entities). So my entity class says @Annotation\Type("Fieldset")
, and a Fieldset gets instantiated when I invoke createForm()
on the AnnotationBuilder -- so far so good. But I have not been able to do get the validators to run against the fieldset elements. As an experiment, I have a controller action doing this:
$em = $this->serviceManager->get('entity-manager');
$builder = new \Zend\Form\Annotation\AnnotationBuilder($em);
$form = new \Zend\Form\Form('person-form');
$hydrator = new \DoctrineModule\Stdlib\Hydrator\DoctrineObject($em);
$form->setHydrator($hydrator);
$fieldset = $builder->createForm(\Application\Entity\Person::class);
$fieldset->setHydrator($hydrator)
->setObject(new \Application\Entity\Person())
->setUseAsBaseFieldset(true);
// more about this later....
$element = new \DoctrineModule\Form\Element\ObjectSelect('hat',
[
'object_manager' => $em,
'target_class' => 'Application\Entity\Hat',
'property' => 'name',
'label' => 'hat',
'display_empty_item' => true,
]);
$fieldset->add($element);
$form->add($fieldset);
$filter = $form->getInputFilter();
$filter->add([
'person' => [
'name' => 'hat',
'validators' =>[
[
'name' => 'Zend\Validator\NotEmpty',
'options' => [
'messages' => [
'isEmpty' => 'the "hat" is required'
],
],
],
],
],
]);
// so anyway...
$viewModel = new ViewModel(['form' => $form]);
$request = $this->getRequest();
if ($request->isPost()) {
$data = $request->getPost();
$person = new \Application\Entity\Person();
$form->bind($person);
$form->setData($data);
if (! $form->isValid()) {
echo "not valid ...messages? ";
\Zend\Debug\Debug::dump($fieldset->getMessages());
return $viewModel;
}
$em->persist($person);
$em->flush();
$this->flashMessenger()->addMessage("congratulations! you inserted an entity.");
return $this->redirect()->toRoute('home');
}
return $viewModel;
}
and what happens when I submit the form is that ìsValid()
returns false, I get the generic "value is required and can't be empty" for the "hat" element that I added after the fact, and none of the validators seem to run against the other fields (error messages array is otherwise empty). So, I would like to know the proper way to create a Fieldset as opposed to a Form via annotations and the AnnotationBuilder. Note that when I do all of this with an annotation-created Form rather than Fieldset, it all works fine.
Second, I would like to be able to mix and match elements (and filters and validators) created via annotations with others added on the fly. Why? Well, the idea of having a max length validator for a string living right alongside the Doctrine annotation that specifies the column width makes good sense to me, plus all the other benefits of these annotations -- I know not everyone is crazy about them. So, the "Hat" element in the example below is such an element, i.e., one I want to add after the form has been instantiated and otherwise initialized. And again, that does work with a Form as opposed to a Fieldset. (Actually, I would be glad to add the element via annotation but it doesn't seem possible to do that with exotic form elements whose constructors have dependencies -- question for another day.)
For the record, here is the Entity class in pertinent part
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
* @Annotation\Name("person")
* @Annotation\Type("Fieldset")
* //Annotation\Type("Form")
* @ORM\Entity @ORM\Table(name="people",uniqueConstraints={@ORM\UniqueConstraint(name="hat_email_idx",columns={"email","hat_id"})})
* @ORM\InheritanceType("JOINED")
*
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"person" = "Person", "interpreter"="Interpreter", "judge"="Judge"})
*/
class Person
{
/**
* entity id
* @Annotation\Exclude()
* @ORM\Id @ORM\GeneratedValue @ORM\Column(type="smallint",options={"unsigned":true})
*/
protected $id;
/**
* the Person's email address.
*
* @ORM\Column(type="string",length=50,nullable=true)
*
* @var string
*/
protected $email;
/**
* the Person's last name.
*
* @Annotation\Options({"label":"last name"})
* @Annotation\Filter({"name":"StringTrim"})
* @Annotation\Validator({"name":"NotEmpty",
* "break_chain_on_failure": true,
* "options":{"messages":{"isEmpty":"last name is required"}
* }})
* @Annotation\Validator({
* "break_chain_on_failure": true,
* "name":"Application\Form\Validator\ProperName",
* "options" : {"type":"last"}
* })
* @Annotation\Validator({"name":"StringLength", "options":{"min":2, "max":50,
* "messages":{"stringLengthTooShort":"name must be at least 2 characters long",
* "stringLengthTooLong":"name exceeds maximum length of 50 characters"}}})
*
* @ORM\Column(type="string",length=50,nullable=false)
* @var string
*/
protected $lastname;
/**
* Everyone must where a hat in this life.
*
* @ORM\ManyToOne(targetEntity="Hat",fetch="EAGER")
* @ORM\JoinColumn(nullable=false)
*
* @var Hat
*/
protected $hat;
// etc etc omitted
}
Many thanks in advance.