Drupal — node form validation methods in hook_form_alter should be set using #after_build to always execute on form submission — Rahul Singla

Last week, I was trying to add a custom validation method for node form of a particular content type in Drupal. My initial approach was as naive as specifying my custom validation method in hook_form_alter, something like the following:

{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }function mymodule_form_alter(&$form, &$form_state, $form_id) {
switch($form_id) {
case ‘artist_node_form’:
$form[‘#validate’][] = ‘_mymodule_custom validation’;
break;
}
}{/syntaxhighlighter}

However my custom validation method was not always called when the node form was submitted. Confused, on a little testing and stepping through the Drupal code, I found that the custom validation method was only called when all core Drupal validation methods on the node form succeeded. If any native validation on the node form (where native means the validations performed by Drupal on the submitted form content based on your assocaited content type’s settings) failed, then the custom validation method was not called.

And this was not what I wanted. This meant that the user did not see all data entry errors on the form together. Only when the first set (i.e. Drupal’s validations) on the form passed was the next set of validation methods (i.e. the custom validation methods on the node form) were invoked. So, after getting errors first time, correcting those and re-submitting, the user might again get validation failures triggered by custom validation, which was not very user-friendly.

Clearly I needed a way to somehow tell Drupal to always invoke the custom validation method on each form submission, so that all validation errors could be shown to the user together.

After some playing around, I decided to hook my custom validation method in the #after_build method instead of doing it in hook_form_alter. So, the updated code looked something like the following:

{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }function mymodule_form_alter(&$form, &$form_state, $form_id) {
switch($form_id) {
case ‘artist_node_form’:
$form[‘#after_build’][] = ‘mymodule_custom_after_build’;
break;
}
}

function mymodule_custom_after_build($form, &$form_state) {
$form[‘#validate’][] = ‘mymodule_custom_validation’;

return($form);
}

function mymodule_custom_validation($form, &$form_state) {
//My custom validations went here.
}{/syntaxhighlighter}

Here I specify #after_build method for the node form in hook_form_alter. Then in the #after_build method, I specify the #validate method for the custom validation I needed.

And it now worked exactly as I needed. My custom validation method was always called which meant all input errors were shown to the user together on each form submission for the node form.

An important point to take care above is that you need to return the $form object from the #after_build method, or it won’t work.

It lacked sense to me that Drupal does not invoke the additional validation methods when specified directly in hook_form_alter but invokes them when spcified in the after_build method for the form. I searched a bit and found this issue being reported on the official Drupal issue queue on drupal.org, but which was closed with a comment that it works as designed. For me, this is not the correct design, but then, every developer has his own way of looking at things…
Atleast there’s was way to have it done so that functionally it behaves as you want it to.

Originally published at https://www.rahulsingla.com on March 16, 2018.