Forms and CSRF protection
This page is for developers used to Symfony Form types, Laravel form requests, Django forms or Rails form helpers.
Exponential has no form component that builds, binds and validates a form object. A form is HTML in a template; the
view reads the posted values through the kernel's helpers and module actions; and the ezformtoken extension
protects POST requests against cross-site request forgery without code in your forms.
Contents
- The parts of a form
- CSRF protection with ezformtoken
- Reading input
- POST, redirect, GET
- Uploads
- Forms for visitors
- Compared with other frameworks
The parts of a form
| Part | Where |
|---|---|
| The HTML form | your template, posting to your view: <form method="post" action={'expdemo/edit/42'|ezurl}> |
| Buttons as actions | single_post_actions in module.php: array( 'StoreButton' => 'Store', 'CancelButton' => 'Cancel' ) |
| Values per action | post_action_parameters: array( 'Store' => array( 'Title' => 'ItemTitle' ) ) |
| Reading | $Module->isCurrentAction( 'Store' ), $Module->actionParameter( 'Title' ), or eZHTTPTool |
| Validation and errors | your code; errors passed back to the template (Validation) |
A worked form is in Task: build a small CRUD module.
CSRF protection with ezformtoken
ezformtoken registers two listeners (Middleware):
response/output: adds a hidden token field to everymethod="post"form in the page for a signed-in user with a session. Your templates need nothing.request/input: refuses a POST of such a user without the right token, taken from the form field or from theX-CSRF-Tokenheader. The answer is a 403 "This form has expired" page (or a JSON body for XHR and JSON requests) and one line invar/log/warning.log, never the token itself (Form expired page).
Set your own secret per installation in settings/override/site.ini.append.php:
[HTMLForms]
Secret=<a long random value of your own>JavaScript that posts with fetch() sends the token in the X-CSRF-Token header; read it from the page rather than
switching the check off (Forms, CSRF protection and HTTP input).
Anonymous visitors have no session to bind a token to, so their POSTs are not checked by ezformtoken. Public forms
are protected with other means: a CAPTCHA from the recaptcha or hcaptcha extension and server-side validation
(Spam protection for forms).
Reading input
$http = eZHTTPTool::instance();
if ( $http->hasPostVariable( 'Title' ) )
$title = trim( (string)$http->postVariable( 'Title' ) );
$page = $http->hasGetVariable( 'page' ) ? max( 1, (int)$http->getVariable( 'page' ) ) : 1;Never read $_POST or $_GET directly: under Velocity the kernel prepares them per request.
POST, redirect, GET
if ( $Module->isCurrentAction( 'Store' ) && $errors === array() )
{
$item->store();
return $Module->redirectTo( '/expdemo/item/' . (int)$item->attribute( 'id' ) );
}Redirect targets taken from the request must stay on the site (Safe redirects).
Uploads
if ( eZHTTPFile::canFetch( 'File' ) )
{
$file = eZHTTPFile::fetch( 'File' );
// check $file->attribute( 'mime_type' ) and size against an allow list before storing
}For files that belong to content, create an object of the file or image class instead; it handles storage,
clustering and SVG sanitizing (Creating and updating content in code).
Forms for visitors
Contact forms, polls and feedback usually need no PHP: a content class with information collector attributes collects the answers, and the administration lists them (Forms with the information collector, Building a contact form).
Compared with other frameworks
| Framework | Concept | Exponential |
|---|---|---|
| Symfony | form types, handleRequest(), CSRF option | template plus module actions; ezformtoken |
| Laravel | form requests, @csrf | your validation in the view; token added automatically for signed-in users |
| Django | Form classes, {% csrf_token %} | the same split; information collector for simple public forms |
| Rails | form_with, strong parameters | action parameters declared in module.php |
Related pages
- Forms, CSRF protection and HTTP input
- Forms in templates
- Responses, redirects, errors and JSON
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.