Within \Drupal\Core\Form\Form\FormBuilder::buildForm, if $cache_check is true, i.e. - the form has a form_id and a build_form_id, then the $form_state object which results from the call made to retrieveForm() in \Drupal\Core\Form\FormBuilder::buildForm() is overwritten by the form_state that is cloned prior to the retrieval. This would seem to effectively nullify any modification done to the $form_state object within the buildForm() method of a Form class implementing FormInterface. Is this correct?

For example, MyForm class extends FormBase -- which implements FormInterface. If I make a call to $form_state->setValidateHandlers() within the buildForm method of the MyForm class, the extra validate handler methods set in that call will never be invoked, as the $form_state object will be overwritten after being rebuilt within MyForm::buildForm().

Is this the expected behavior? i.e. - Is it not expected to be able to alter the $form_state within buildForm() in this way? If that is the case, then is simply using the more "Drupal 7-ish" syntax of $form['#validate'] = ['::method1', '::method2'] the accepted/best-practice way to accomplish multiple validate handlers? This will work, because the $form array does not get overwritten after the MyForm::buildForm() method is invoked. However, if this is the accepted/best-practice way to achieve multiple validate handlers, how would one set a validate handler that exists outside of the current form class (in this example's case, MyForm)?

Comments

axlroach created an issue. See original summary.

tim.plunkett’s picture

Status: Active » Fixed

The ::methodName version is just shorthand. It gets expanded to [$form_object, 'methodName'].
You should not use setValidationHandlers() directly, your explanation is correct.

$form['#validate'][] = [$any_object, 'anyMethod'];
$form['#validate'][] = [Drupal\whatever\MyClass::class, 'anyStaticMethod'];
$form['#validate'][] = 'Drupal\whatever\MyClass::anyStaticMethod';

Any of these will work

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.