2011-02-07 07:48:44 +01:00
|
|
|
# Form Validation
|
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
SilverStripe provides PHP form validation out of the box,
|
|
|
|
but doesn't come with any built-in JavaScript validation
|
|
|
|
(the previously used `Validator.js` approach has been deprecated).
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
## Required Fields
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
Validators are implemented as an argument to the `[api:Form]` constructor,
|
|
|
|
and are subclasses of the abstract `[api:Validator]` base class.
|
|
|
|
The only implementation which comes with SilverStripe is
|
|
|
|
the `[api:RequiredFields]` class, which ensures fields are filled out
|
|
|
|
when the form is submitted.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2012-01-30 23:13:42 +01:00
|
|
|
public function Form() {
|
2011-02-07 07:48:44 +01:00
|
|
|
$form = new Form($this, 'Form',
|
2011-10-28 03:37:27 +02:00
|
|
|
new FieldList(
|
2011-02-07 07:48:44 +01:00
|
|
|
new TextField('MyRequiredField'),
|
|
|
|
new TextField('MyOptionalField')
|
|
|
|
),
|
2011-10-28 03:37:27 +02:00
|
|
|
new FieldList(
|
2012-06-28 11:43:30 +02:00
|
|
|
new FormAction('submit', 'Submit form')
|
2011-02-07 07:48:44 +01:00
|
|
|
),
|
|
|
|
new RequiredFields(array('MyRequiredField'))
|
|
|
|
);
|
|
|
|
// Optional: Add a CSS class for custom styling
|
|
|
|
$form->dataFieldByName('MyRequiredField)->addExtraClass('required');
|
|
|
|
return $form;
|
|
|
|
}
|
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
## Form Field Validation
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
Form fields are responsible for validating the data they process,
|
|
|
|
through the `[api:FormField->validate()] method. There are many fields
|
|
|
|
for different purposes (see ["form field types"](/reference/form-field-types) for a full list).
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
## Adding your own validation messages
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
In many cases, you want to add PHP validation which is more complex than
|
|
|
|
validating the format or existence of a single form field input.
|
|
|
|
For example, you might want to have dependent validation on
|
|
|
|
a postcode which depends on the country you've selected in a different field.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
There's two ways to go about this: Either you can attach a custom error message
|
|
|
|
to a specific field, or a generic message for the whole form.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
Example: Validate postcodes based on the selected country (on the controller).
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
:::php
|
|
|
|
class MyController extends Controller {
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $allowed_actions = array('Form');
|
2012-06-28 11:43:30 +02:00
|
|
|
public function Form() {
|
|
|
|
return Form::create($this, 'Form',
|
|
|
|
new FieldList(
|
|
|
|
new NumericField('Postcode'),
|
|
|
|
new CountryDropdownField('Country')
|
|
|
|
),
|
|
|
|
new FieldList(
|
|
|
|
new FormAction('submit', 'Submit form')
|
|
|
|
),
|
|
|
|
new RequiredFields(array('Country'))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
public function submit($data, $form) {
|
|
|
|
// At this point, RequiredFields->validate() will have been called already,
|
|
|
|
// so we can assume that the values exist.
|
2012-10-02 00:02:17 +02:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
// German postcodes need to be five digits
|
|
|
|
if($data['Country'] == 'de' && isset($data['Postcode']) && strlen($data['Postcode']) != 5) {
|
|
|
|
$form->addErrorMessage('Postcode', 'Need five digits for German postcodes', 'bad');
|
|
|
|
return $this->redirectBack();
|
|
|
|
}
|
2012-10-02 00:02:17 +02:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
// Global validation error (not specific to form field)
|
|
|
|
if($data['Country'] == 'IR' && isset($data['Postcode']) && $data['Postcode']) {
|
|
|
|
$form->sessionMessage("Ireland doesn't have postcodes!", 'bad');
|
|
|
|
return $this->redirectBack();
|
|
|
|
}
|
|
|
|
|
|
|
|
// continue normal processing...
|
|
|
|
}
|
2011-02-07 07:48:44 +01:00
|
|
|
}
|
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
## JavaScript Validation
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
While there are no built-in JavaScript validation handlers in SilverStripe,
|
|
|
|
the `FormField` API is flexible enough to provide the information required
|
|
|
|
in order to plug in custom libraries.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
### HTML5 attributes
|
|
|
|
|
|
|
|
HTML5 specifies some built-in form validations ([source](http://www.w3.org/wiki/HTML5_form_additions)),
|
|
|
|
which are evaluated by modern browsers without any need for JavaScript.
|
|
|
|
SilverStripe supports this by allowing to set custom attributes on fields.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2012-06-28 11:43:30 +02:00
|
|
|
// Markup contains <input type="text" required />
|
|
|
|
TextField::create('MyText')->setAttribute('required', true);
|
2012-10-02 00:02:17 +02:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
// Markup contains <input type="url" pattern="https?://.+" />
|
|
|
|
TextField::create('MyText')
|
|
|
|
->setAttribute('type', 'url')
|
|
|
|
->setAttribute('pattern', 'https?://.+')
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
### HTML5 metadata
|
|
|
|
|
|
|
|
In addition, HTML5 elements can contain custom data attributes with the `data-` prefix.
|
|
|
|
These are general purpose attributes, but can be used to hook in your own validation.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
:::php
|
2012-06-28 11:43:30 +02:00
|
|
|
// Validate a specific date format (in PHP)
|
|
|
|
// Markup contains <input type="text" data-dateformat="dd.MM.yyyy" />
|
|
|
|
DateField::create('MyDate')->setConfig('dateformat', 'dd.MM.yyyy');
|
2012-10-02 00:02:17 +02:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
// Limit extensions on upload (in PHP)
|
|
|
|
// Markup contains <input type="file" data-allowed-extensions="jpg,jpeg,gif" />
|
|
|
|
$exts = array('jpg', 'jpeg', 'gif');
|
|
|
|
$validator = new Upload_Validator();
|
|
|
|
$validator->setAllowedExtensions($exts);
|
|
|
|
$upload = Upload::create()->setValidator($validator);
|
|
|
|
$fileField = FileField::create('MyFile')->setUpload(new);
|
|
|
|
$fileField->setAttribute('data-allowed-extensions', implode(',', $exts));
|
|
|
|
|
|
|
|
Note that these examples don't have any effect on the client as such,
|
|
|
|
but are just a starting point for custom validation with JavaScript.
|
|
|
|
|
|
|
|
## Model Validation
|
|
|
|
|
|
|
|
An alternative (or additional) approach to validation is to place it directly
|
|
|
|
on the model. SilverStripe provides a `[api:DataObject->validate()]` method for this purpose.
|
|
|
|
Refer to the ["datamodel" topic](/topics/datamodel#validation-and-constraints) for more information.
|
|
|
|
|
|
|
|
## Subclassing Validator
|
2011-02-07 07:48:44 +01:00
|
|
|
|
2012-06-28 11:43:30 +02:00
|
|
|
To create your own validator, you need to subclass validator and define two methods:
|
|
|
|
|
|
|
|
* **javascript()** Should output a snippet of JavaScript that will get called to perform javascript validation.
|
|
|
|
* **php($data)** Should return true if the given data is valid, and call $this->validationError() if there were any
|
|
|
|
errors.
|
2011-02-07 07:48:44 +01:00
|
|
|
|
|
|
|
## Related
|
|
|
|
|
|
|
|
* Model Validation with [api:DataObject->validate()]
|