Server-side form validation
From Joomla! Documentation
After submitting a form, you should validate your data. In Joomla this can be done via the JForm validate method (normally called in the controller via the model JModelForm).
Unlike client-side validation, the validation uses html attributes to do its validation. There is the attribute required ("true" or "required") which makes a field required and the attribute validate with a joomla or custom rule value.
E.g. field in a joomla form xml
<field name="email" type="text" class="inputbox" description="Fill in your E-mail" label="E-mail" required="true" validate="email" size="30" />
You can find the specific implementation of these rules in /libraries/joomla/form/form.php - validation begins in the function validate(), moves to validateField(), which then calls the respective validation functions of /libraries/joomla/form/rule/*.php
Custom Validation rules[edit]
Its very easy to add custom validation rules to your form elements. You can easily extend the JFormRule class to do this.
Add the rule path to your form:
In your form.xml file, add to the fieldset the following:
<form>
<fieldset name="form_name" addrulepath="components/com_yourcomponent/models/rules">
</fieldset>
</form>
This tells your form to look at:
<joomla_root>/components/com_yourcomponent/models/rules/*.php
And auto-loads any of the php files here which will have classes that act as rules.
Extend JFormRule
Create your rule file at:
<joomla_root>/components/com_yourcomponent/models/rules/[rule].php
For example:
<joomla_root>/components/com_yourcomponent/models/rules/date.php
The contents of the file is important as well. You must extend the JFormRule class:
class JFormRuleDate extends JFormRule
The suffix of the classname (JFormRule[SUFFIX]) must be the same as the rule file name. For date.php, the class name should be JFormRuleDate. For integer you would have integer.php, and JFormRuleInteger.
Use a Regex, or override the test function
There's two ways to write the validator. The first and possibly easier is to simply override the $regex property of the JFormRule class. For an integer rule, the entire class looks like this:
class JFormRuleInteger extends JFormRule
{
protected $regex = '[0-9]';
}
But often times you want a slightly more complex validation rule, to do this its easier to override the test() method, providing your own implementation and ignoring the regex entirely.
For example, to test the format of a date:
public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
{
$dt = DateTime::createFromFormat("m/d/Y", $value);
if ($dt instanceof DateTime) {
return true;
}
return false;
}
Note: The test() method already exists in the JFormRule class, so here you are just extending the existing method.
All you need to do is make sure the method returns a 'true' or 'false' boolean when its done. It can call other methods and do any amount of checks to verify the entered value is correct.
Call the validation from your JForm Field
The last step in the validation process is to tell your form field which validation rule to use. This is easy. Just add the reference of the rule name to the Jform XML for the input element:
<field name="date_issued" type="calendar" label="COM_YOURCOMPONENT_LABEL" hint="COM_YOURCOMPONENT_HINT"
description="COM_YOURCOMPONENT_DESC" size="20" required="true" class="form-control col-md-5" validate="date" format="%m/%d/%Y"
/>
The important part of that is the validate="date" part. Again, that must match the suffix of the JFormRule[SUFFIX], and the rule's filename: [suffix].php (in the models/rules directory).
Add a custom validation message
You may want to display a more useful message than the standard "Warning: Invalid Field".
For messages that don't need to be dynamic add a "message" attribute to your form field.
<field name="date_issued" type="calendar" label="COM_YOURCOMPONENT_LABEL" hint="COM_YOURCOMPONENT_HINT"
description="COM_YOURCOMPONENT_DESC" size="20" required="true" class="form-control col-md-5" validate="date" format="%m/%d/%Y" message="Your custom validation messsage goes here"
/>
You can provide a more dynamic message too. Say you want to include a variable in the message, or you do multiple tests inside the test() function which obviously may lead to different failure reasons, then you can add the custom and dynamic message from within the test() function.
public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
{
/* test 1 */
if ($value < 1) {
$element->attributes()->message = 'The value ' . $value . ' is not valid because it is less than 1';
// The above line works if you have already specified a custom message by adding the message="..." attribute
// to your form field. If you haven't then use instead
// $element->addAttribute('message', 'The value ' . $value . ' is not valid because it is less than 1');
return false;
}
/* test 2 */
if ($value > 1000) {
$element->attributes()->message = 'The value ' . $value . ' is not valid because it is greater than 1000';
return false;
}
return true;
}