0
votes

I don't know why, but I remembered that when you have a symfony form with required fields not rendered, the isValid function do not check for them.

I mean it only check if the widget got a value when you use it. And it seem in my current project that it is wrong.

Is there a setting or something allowing to do this ?

Edit : Here is the form :

    class DemandeForm extends BaseDemandeForm
    {
  public function configure()
  {
    $this->widgetSchema['DEMANDE_DESC']         = new sfWidgetFormTextarea();
    $this->validatorSchema['DEMANDE_DESC']      = new sfValidatorString(array('required' => true),
    array("required" => str_replace('$1','Description de la demande',MessagePeer::getFrameworkMessageFromNum(7))));

    $this->validatorSchema['DEMANDE_LIB']      = new sfValidatorString(array('required' => true),
    array("required" => str_replace('$1','Libelle de la demande',MessagePeer::getFrameworkMessageFromNum(7))));

    $this->widgetSchema['TIERS_ID']         = new crfcWidgetAutocomplete();
    $this->validatorSchema['TIERS_ID']      = new sfValidatorString(array('required' => true),
    array("required" => str_replace('$1','Tiers',MessagePeer::getFrameworkMessageFromNum(7))));

    $bat_choices = $this->getOption('bat_choices');
    $this->widgetSchema['BAT_CODE']         = new sfWidgetFormChoice(array('choices' => $bat_choices , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['BAT_CODE']      = new sfValidatorChoice(array('choices' => array_keys($bat_choices),'required' => false)
    );

    $local_choices = $this->getOption('local_choices');
    $this->widgetSchema['LOCAL_CODE']       = new sfWidgetFormChoice(array('choices' => $local_choices, 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['LOCAL_CODE']    = new sfValidatorChoice(array('choices' => array_keys($local_choices),'required' => false)
    );

    $site_choices = $this->getOption('site_choices');
    $this->widgetSchema['SITE_CODE']       = new sfWidgetFormChoice(array('choices' => $site_choices, 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['SITE_CODE']    = new sfValidatorChoice(array('choices' => array_keys($site_choices),'required' => false)
    );

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('FONCTIONS',true);
    $this->widgetSchema['FONCTION_EVAL_NUMINT']         = new sfWidgetFormChoice(array('choices' => $ress , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['FONCTION_EVAL_NUMINT']      = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => false),
    array("required" => str_replace('$1','Fonction demandeur',MessagePeer::getFrameworkMessageFromNum(7))));

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('CIRCONSTANCE',true);
    $this->widgetSchema['CIRCONSTANCE_EVAL_NUMINT']       = new sfWidgetFormChoice(array('choices' => $ress, 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['CIRCONSTANCE_EVAL_NUMINT']    = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => false),
    array("required" => str_replace('$1','Circonstance de la demande',MessagePeer::getFrameworkMessageFromNum(7))));

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('TRAVAUX',true);
    $this->widgetSchema['CATEGORIE_EVAL_NUMINT']         = new sfWidgetFormChoice(array('choices' => $ress , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['CATEGORIE_EVAL_NUMINT']      = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => false),
        array("required" => str_replace('$1','Catégorie de travaux',MessagePeer::getFrameworkMessageFromNum(7)))
    );

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('QUALIFICATION',true);
    $this->widgetSchema['QUALIFICATION_EVAL_NUMINT']         = new sfWidgetFormChoice(array('choices' => $ress , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['QUALIFICATION_EVAL_NUMINT']      = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => true),
        array("required" => str_replace('$1','Qualification',MessagePeer::getFrameworkMessageFromNum(7)))
    );

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('PROGRAMME',true);
    $this->widgetSchema['PROGRAMME_EVAL_NUMINT']         = new sfWidgetFormChoice(array('choices' => $ress , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['PROGRAMME_EVAL_NUMINT']      = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => true),
            array("required" => str_replace('$1','Programme',MessagePeer::getFrameworkMessageFromNum(7)))
            );

    $ress = Array(""=>"") + EnumereValeurPeer::getByType('SUPPORT',true);
    $this->widgetSchema['SUPPORT_EVAL_NUMINT']         = new sfWidgetFormChoice(array('choices' => $ress , 'expanded' => false, 'multiple' => false));
    $this->validatorSchema['SUPPORT_EVAL_NUMINT']      = new sfValidatorChoice(array('choices' => array_keys($ress),'required' => false),
    array("required" => str_replace('$1','Support',MessagePeer::getFrameworkMessageFromNum(7))));

    $this->widgetSchema['COMMENTAIRE']         = new sfWidgetFormTextarea();
    $this->validatorSchema['COMMENTAIRE']      = new sfValidatorString(array('required' => false));


    $this->widgetSchema['DEMANDE_DTDEM']                    = new myWidgetFormRichDate();
    $this->validatorSchema['DEMANDE_DTDEM']                 = new sfValidatorDate(array('required' => true, 'date_format'=>'@(?P<day>\d{2})/(?P<month>\d{2})/(?P<year>\d{4})@'),
        array('required'=> str_replace('$1','Date de la demande',MessagePeer::getFrameworkMessageFromNum(7)),
        'bad_format' => str_replace('$1','Date de la demande',MessagePeer::getFrameworkMessageFromNum(19)),
        'invalid' => str_replace('$1','Date de la demande',MessagePeer::getFrameworkMessageFromNum(19))));

    $this->widgetSchema['DEMANDE_DTFIN']                    = new myWidgetFormRichDate();
    $this->validatorSchema['DEMANDE_DTFIN']                 = new sfValidatorDate(array('required' => true, 'date_format'=>'@(?P<day>\d{2})/(?P<month>\d{2})/(?P<year>\d{4})@'),
        array('required'=> str_replace('$1','Date de fin des travax souhaitée',MessagePeer::getFrameworkMessageFromNum(7)),
        'bad_format' => str_replace('$1','Date de fin des travax souhaitée',MessagePeer::getFrameworkMessageFromNum(19)),
        'invalid' => str_replace('$1','Date de fin des travax souhaitée',MessagePeer::getFrameworkMessageFromNum(19))));

    $this->widgetSchema['DEMANDE_ACCESSIBILITE']            = new sfWidgetFormInputCheckbox();
    $this->validatorSchema['DEMANDE_ACCESSIBILITE']         = new sfValidatorBoolean(array('required' => false));

    $this->widgetSchema['DEMANDE_URGENT']                   = new sfWidgetFormInputCheckbox();
    $this->validatorSchema['DEMANDE_URGENT']                = new sfValidatorBoolean(array('required' => false));

    $this->widgetSchema['DEMANDE_INCENDIE']                 = new sfWidgetFormInputCheckbox();
    $this->validatorSchema['DEMANDE_INCENDIE']              = new sfValidatorBoolean(array('required' => false));

    $this->validatorSchema->setOption('allow_extra_fields' , true);
    $this->validatorSchema->setOption('filter_extra_fields' , false);
  }


}

Edit 2 :

The question is : is it normal than the DEMANDE_DTDEM field required, raise a required form field error, whereas he hadn't been rendered ?

Shouldn't a form field be validated only when he was used ?

2
And you got an error like "Extra field name."? Ot sth else? - j0k
No, my workflow has 2 steps. Almost all fields are used in one place in order to create or edit this model. But 2 are used later in order to validate the model (not the same user). In the validation case, the $this->form->isValid(), raise required errors. On all the required fields i hadn't used. Is his normal ? - Perello
You are using the same form class for both step? - j0k
Yeah. I don't know why, i thought i was possible. Maybe through workarounds. I'm trying to stay consistent with most of the symfony project i have to work on. And each one was using a same form to different place, and not always with the same fields. I don't think that's a best practice still, but it remove duplicate widget declaration. - Perello

2 Answers

3
votes

Yes, it's the normal behaviour. Fields VALIDATION has nothing to do with rendering. If you don't want to render a widget you must explicitly remove both widget and validator (with unset or useFields).

If you define a widget and a validator (like in your case), but you don't call to $form['DTDEM']->render(), the value will be always empty.

IT'S VERY IMPORTANT THAT YOU UNDERSTAND THAT. In this case, the field is required, and then become that error, but if it wasn't required, the $form->save() method will always clean the value of the object in your database!

NEVER leave the widgets unrendered. You should do some echo $form while debugging to see what widgets are configured, and if you don't want some of them, just remove them in the form configure() method (as I said, with unset or useField)

0
votes

I wish to add a complement to the glerendegui's answer.

What he is said is true in the general case. But, there is an element game changing. The form's option filter_extra_fields(false) alter significantly the rules. And is the reason for my original misunderstanding.

Because with this option set to false, the $form->save() will not set empty values in your objets, when you widget have not been rendered.

This is an important addition, because in all legacy code i have inherited, the use of this option was common, and unchallenged.