Not every value a form needs to carry through a submission belongs in front of the user. A hidden field lets you pass data along with the form — an ID, a token, a computed value from an earlier step — without rendering any visible input at all.
What you'll learn in this lesson
- The basic hidden field definition
- Why hidden fields are for carrying data, not for protecting it
- A real use case: passing an entity ID through a multi-step form
A basic hidden field
$form['entity_id'] = [
'#type' => 'hidden',
'#value' => $node->id(),
];
Notice this uses #value, not #default_value — a hidden field has no visible UI a user could ever edit, so there's no distinction between "initial value" and "current value" the way there is for a visible text field. #value forces the value directly, and it's what gets submitted, full stop.
A real use case: multi-step state
$form['step'] = [
'#type' => 'hidden',
'#value' => $form_state->get('current_step') ?? 1,
];
This is a common pattern in hand-rolled multi-step forms (before you'd typically reach for $form_state->set()/get() directly, which is usually the better tool) — carrying a piece of state across submissions by round-tripping it through the form itself as a hidden value.
Quick check: you store a product's price in a hidden field so the submit handler can charge the right amount. Is this safe? (No — a user can edit the hidden field's value in their browser before submitting, changing the price to anything they want. Always re-look up the real price server-side from the product's actual stored data, never trust a client-submitted value for anything with real consequences.)
Key takeaways
- Hidden fields use
#value, not#default_value— there's no visible state to distinguish between. - A hidden field is invisible in the rendered UI, but its value is fully visible and editable in the raw HTML/request — never rely on it for security.
- For anything sensitive or consequential, re-validate against real server-side data in your submit handler, regardless of what a hidden field claims.
Coming up next
Next up: a genuinely tricky element type to get right — date and datetime fields, and the timezone/format gotchas that come with them.