1
votes

I use Annotation in a Doctrine Entity Class. Annotation for a field are :

   /**
 * @var integer
 *
 * @ORM\Column(name="duree", type="integer", nullable=true)
 *
 * @Form\Type("Zend\Form\Element\Number")
 * @Form\Attributes({"required":false, "placeholder":"Durée", "min":"1", "max":"20"})
 * @Form\Required(false)
 * @Form\AllowEmpty()
 * @Form\Options({"label":"Durée :"})
 * @Form\Filter({"name": "Int"})
 * @Form\Validator({"name":"IsInt"})
 */
private $duree;

So the DB column can be Empty (nullable), and in the form i wan't the same (ie user can leave input empty). I've both annotation Required(false) and allowEmpty, but the form never valid (always got isEmpty for this field).

If i set @Form\Type to "Text", it is working fine (form is valid event if input is empty). But with the class Number, it'is not the same.

I've the same pb with a Select element (correspondinf to a relationship). Annotations are :

    /**
 * @var \Application\Entity\CcCategorie
 *
 * @ORM\ManyToOne(targetEntity="Application\Entity\CcCategorie")
 * @ORM\JoinColumns({
 *   @ORM\JoinColumn(name="categorie", referencedColumnName="id", nullable=true, onDelete="SET NULL")
 * })
 * 
 * @Form\Type("DoctrineModule\Form\Element\ObjectSelect")
 * @Form\Attributes({"type":"select", "required":false})
 * @Form\Options({"label":"Catégorie :"})
 * @Form\Required(false)
 * @Form\AllowEmpty()
 * @Form\Options({
 *      "label":"Catégorie :",
 *      "empty_option": "---",
 *      "target_class": "Application\Entity\CcCategorie",
 *      "property": "label"
 * })     
 */
private $categorie;

But, with this the field has error (isEmpty) if the Select is set to empty option when validating Form.

The only workaround i've found is to set the annotation

 * @Form\Type("\Application\Form\Entity\CcRepriseFieldset")

at the top of the entity class. The class CcRepriseFieldset extend Fieldset, and implement InputFilterProviderInterface. Then i specify the function in this class :

public function getInputFilterSpecification()
    {
        return array(
            array(
                "name" => "duree",
                'required' => false,
                'allow_empty' => true,
            ),
            array(
                "name" => "categorie",
                'required' => false,
                'allow_empty' => true,
            ),
        );
    }

With this it works... But it's not annotations. I don't understand why annotation not work

thanks

2
Man, some advice - step away from form annotations. Build proper, cacheable code and separate your input filters from form construction; this little blog post might help circlical.com/blog/2015/7/6/… - Saeven
Have you tried explicitly indicating allow empty should be true? ie @Form\AllowEmpty(true) I don't use form annotations (same opinion as @Saeven ) but I'd fully expect leaving the parameter empty as you have to be interpreted as a falsey value - Crisp
@Saeven Thanks for help. I found a advantage in using Doctrine and Form annotations : All information are in the same place. I found there is a sense that if the ORM definition is type="integer", nullable=true, in the same place you define that the form field wich hold this data is a Number that allow empty value and have Int Validator and filter, and of course have exactly the same name. When you need to change something in the database, you only have to edit the dotblock and then run doctrine tool to change the db. All other setting are in the class (extending Fieldset ) associated. - gregf
@Crisp According to ZF 2 doc "AllowEmpty: mark an input as allowing an empty value. This annotation does not require a value." But i've try your suggest, with no succes result. Thank for your idea - gregf

2 Answers

0
votes

Ok i found what is the probleme. Annotation Builder made a array with all fields spec, like this :

 array (size=7)
    'name' => string 'reprise' (length=7)
    'attributes' => array (size=0)
    'elements' => 
      array (size=8)
      1 =>array (size=2)
...
  'fieldsets' => array (size=0) empty
  'type' => string '\Application\Form\Entity\CcRepriseFieldset'
(length=42)
  'input_filter' => 
    array (size=8)
      'name' => 
        array (size=4)
          'name' => string 'name' (length=4)
          'required' => boolean true
          'filters' => 
            array (size=3)
              ...
          'validators' => 
            array (size=2)
...

But this array is the Array for the FieldSet attached to the Entity. So the Zend\Form\Factory never parse this because 'input_filter' are only parse for ZendForm Element not for fieldset (of course because Fieldset doesn't have SetInputFilter method)...

0
votes

Ok i've a workaround but i'm not very statisfied of it . First i've create a new FormFactory :

namespace Application\Form;
use Zend\Form\FieldsetInterface;
Class EntityFormFactory extends \Zend\Form\Factory {
     public function configureFieldset(FieldsetInterface $fieldset, $spec)
    {
       $fieldset=parent::configureFieldset($fieldset, $spec);

        $fieldset->input_filter_factory= $spec['input_filter'];
        return $fieldset;
    }
}

So this factory add the "input_filter" to a input_filter_factory variable of the fieldset.

Then in the fieldset class is :

class CcRepriseFieldset extends Fieldset implements \Zend\InputFilter\InputFilterProviderInterface
{
   public function getInputFilterSpecification()
    {
        if (isset($this->input_filter_factory)){
            return $this->input_filter_factory;
        }        
    }
}

And finally, when i use annotationbuilder i change the formfactory :

$builder = new AnnotationBuilder($this->_em);
$builder->setFormFactory(new EntityFormFactory());

With this all is working fine... I'm not sur it's the best way to do it.