The most common validation rule on any form isn't a clever regex or a cross-field comparison — it's simply "don't let this be blank." Drupal handles that single most frequent case with one property, no custom validation method required at all: #required.
What you'll learn in this lesson
- How
#required => TRUEtriggers automatic, built-in validation - Where the "field is required" error message comes from, and how to customize it
- Why
#requiredchecks run before your own custom validators - The difference between an empty string and a genuinely absent value for different element types
Marking a field required
$form['email'] = [
'#type' => 'email',
'#title' => $this->t('Email address'),
'#required' => TRUE,
];
Set #required => TRUE on any element and two things happen automatically, with zero code from you: a red asterisk appears next to the label so the visitor knows before they even try to submit, and Drupal's own built-in validation refuses the submission if that field is left empty — generating a generic but perfectly serviceable error message on its own.
Customizing the required-field message
$form['email'] = [
'#type' => 'email',
'#title' => $this->t('Email address'),
'#required' => TRUE,
'#required_error' => $this->t('We need an email address so we can send your confirmation.'),
];
By default, Drupal's generated message is something like "Email address field is required." — functional, but generic. Set #required_error to override it with wording specific to why the field actually matters, without writing any validation logic yourself.
Required checks run before your own validators
Drupal's own #required check happens automatically as part of core's form processing, before your validateForm() method or any #element_validate callback runs. This matters in practice: if you write a custom validator that reads and processes a field's value, you can generally assume that by the time your code runs, a required field is guaranteed non-empty — you don't need to re-check for blankness yourself on top of #required.
#required understands all of these per-type correctly — you don't need different logic for different element types.See it for yourself
Mark a text field #required => TRUE, submit the form with it blank, and confirm Drupal blocks submission and shows an error — without you writing a single line of validation code. Then add #required_error and confirm your custom wording replaces the generic message.
Quick check: you mark a checkbox
#required => TRUE. What does "required" actually mean for a checkbox — must it be checked, or just present in the submission? (Answer: it must be checked. An unchecked checkbox is Drupal's definition of "empty" for that element type, so#requiredforces the visitor to check it, not merely acknowledge it exists.)
Key takeaways
#required => TRUEgives you automatic required-field validation with zero custom code — plus a visual asterisk on the label.- Override the generated error text with
#required_errorwhen the generic message isn't specific enough. #requiredchecks run before your ownvalidateForm()/#element_validatecallbacks, so you can generally trust a required field is non-empty by the time your custom code runs.- "Empty" is defined per element type: blank string for text fields, unchecked for checkboxes, empty array for multi-value selects/checkboxes groups.
Coming up next
Required-field checks and single-element validators only get you so far. Next, you'll write genuinely custom validation logic in validateForm() itself — the place to reach for when a rule needs to look at more than one field at once.