Required Annotation in Laminas Form

Hi Folks!

I have been trying to get rid of my form classes and use form annotations to create them; however, I stumbled upon a little something…:

Given the following element:

//use statement for completions sake
use Laminas\Form\Annotation as Form;

/**
 * @ORM\Entity
 * @ORM\Table(name="Test")
 * 
 * @Form\Name("Test")
 */
class Test
{
     /**
     * @ORM\Column(type="string")
     *
     * @Form\Type("textarea")
     * @Form\Options({"label" : "Description"})
     * @Form\Attributes({"class" : "form-control", "placeholder" : "Description"})
     * @Form\Required(false)
     * @Form\Filter("StringTrim")
     * @Form\Filter("StripTags")
     * @Form\Validator("StringLength", options={"encoding": "UTF-8", "min": "1", "max": "65000"})
     * 
     * @var string
     */
    public $description;
}

which generates a form specification like this:

{
  "name": "Test",
  "attributes": [],
  "elements": [
    {
      "flags": [],
      "spec": {
        "name": "description",
        "type": "textarea",
        "options": { "label": "Description" },
        "attributes": { "class": "form-control", "placeholder": "Description" }
      }
    }
  ],
  "input_filter": {
    "description": {
      "name": "description",
      "required": true,
      "filters": [
        { "name": "StringTrim" },
        { "name": "StripTags" },
        { "name": "StringTrim" }
      ],
      "validators": [
        {
          "name": "StringLength",
          "options": { "encoding": "UTF-8", "min": "1", "max": "65000" }
        }
      ]
    }
  },
  "options": { "prefer_form_input_filter": true }
}

the thing that irks me, is:
Apparently, something thinks that the element has to be required, even though I clearly set it to false in the Annotation, because I get a “this element is required”-message when I leave it empty and submit the form.
To top it off, there is this line in the ElementAnnotationListener that sets an attribute called “required” to “required” when the element is required. According to above formSpec, that does also not happen.
Is anyone able to enlighten me on how to set an element to optional properly? :slight_smile:

What does the HTML output look like?

<textarea name="description" class="form-control" placeholder="Description"></textarea>

This is the HTML.
For good measure, that’s how I create the form:

        $builder = new EntityBasedFormBuilder($em);

        $form = $builder->createForm($entity);

        $form->setHydrator(new DoctrineObject($em))->setObject($entity);
        $form->bind($entity);

Later, the isValid-check fails and returns; I do not set the inputfilters separately anywhere (I quarter-checked, lol)

Which check fails? By the browser or by the input filter?

Ah, that was unclear, sorry!

$form->isValid() fails, I figure that’s the inputfilter.

The annotation Required does not change the input filter, it is for the HTML attribute. See your own link:

Right, guess I am stupid :smiley:

Anyway, based on what you said, there should be an InputFilter that makes the element optional, right?
Like this:

/**
     * @ORM\Column(type="string")
     *
     * @Form\Type("textarea")
     * @Form\Options({"label" : "Description"})
     * @Form\Attributes({"class" : "form-control", "placeholder" : "Description"})
     * @Form\Required(false)
     * @Form\Filter("StringTrim")
     * @Form\Filter("StripTags")
     * @Form\InputFilter("OptionalInputFilter") //like this here?
     * @Form\Validator("StringLength", options={"encoding": "UTF-8", "min": "1", "max": "65000"})
     * 
     * @var string
     */
    public $description;

But it is still required in the inputfilter-spec:

"description": {
      "name": "description",
      "required": true, //this here
      "filters": [
        { "name": "StringTrim" },
        { "name": "StripTags" },
        { "name": "StringTrim" }
      ],
      "validators": [
        {
          "name": "StringLength",
          "options": { "encoding": "UTF-8", "min": "1", "max": "65000" }
        }
      ]
    },

Am I still missing something?

No, because the fact is missing in the documentation.

Not an entire (optional) input filter is helping here, because only one input must be configured to allow an empty value. See: Using PHP8 Attributes or DocBlock Annotations - laminas-form - Laminas Docs

Using the “AllowEmpty”-annotation did work, thanks!

However, it is marked as deprecated in the documentation; is that right?
Its replacement is the NotEmpty-annotation, which hints that the default behaviour is intended to be “element is optional” (?)

Ignore this deprecation, AllowEmpty works and is intuitive.

1 Like

Try disregarding the Required parameter in general. I have found forms i created that I specified required equals false, and it still inputs the required parameter. If I neglect to use required at all, it allows it to be optional.

1 Like