-
Notifications
You must be signed in to change notification settings - Fork 0
Enforcing validation on user input
Client-side validation in the browser is useful, but it is not enough on its own. Requests can be replayed, forged, edited, or submitted from code that never touched the browser at all.
DomValidation is the server-side step: we pass it the form element and the submitted data, and it checks the input against the rules declared in the HTML.
- Get a reference to the
<form>element in a server-sideHTMLDocument. - Create a
Validator. - Call
validate($form, $input). - Catch
ValidationExceptionif anything is invalid. - Read the error messages from
getLastErrorList().
use GT\Dom\HTMLDocument;
use GT\DomValidation\ValidationException;
use GT\DomValidation\Validator;
// In this example, $input is a key-value-pair of values from the POST data.
function handleSubmit(HTMLDocument $document, array $input):void {
$form = $document->querySelector("#example-form");
$validator = new Validator();
try {
$validator->validate($form, $input);
}
catch(ValidationException) {
foreach($validator->getLastErrorList() as $name => $message) {
$field = $form->querySelector("[name='$name']");
$field?->parentElement?->dataset->validationError = $message;
}
return;
}
// Carry on processing the valid input here.
}The Validator::validate() method takes two arguments:
The first argument must be the form element we want to validate against.
$form = $document->forms[0];Use the actual form element, because the library reads the rule definitions from the current DOM:
- attributes such as
required,pattern,type,min,max, andstep -
<option>values in a<select> - available values in radio and checkbox groups
The second argument may be:
- an associative array
- any iterable object
- an object with public properties
- an object that provides an
asArray()method
That makes the validator easy to use with plain $_POST, with PHP.GT/Input, and with other request wrappers.
There is more detail on accepted input shapes in Working with input data.
If one or more fields are invalid, validate() throws a ValidationException.
The exception message is intentionally broad:
There is 1 invalid fieldThere are 2 invalid fields
The useful detail lives in the validator's ErrorList, which is available immediately afterwards through:
$validator->getLastErrorList()That object can be iterated like this:
foreach($validator->getLastErrorList() as $name => $message) {
// ...
}The key is the form field's name. The value is the combined human-readable hint for that field.
use GT\Dom\HTMLDocument;
use GT\DomValidation\ValidationException;
use GT\DomValidation\Validator;
$document = new HTMLDocument(file_get_contents("payment-form.html"));
if(($_POST["do"] ?? "") === "buy") {
$form = $document->querySelector("#payment-form");
$validator = new Validator();
try {
$validator->validate($form, $_POST);
echo "Payment succeeded!";
exit;
}
catch(ValidationException) {
foreach($validator->getLastErrorList() as $name => $message) {
$field = $form->querySelector("[name='$name']");
$field?->parentElement?->dataset->validationError = $message;
}
}
}
echo $document;Note
In WebEngine, the current HTMLDocument and the request Input object are already part of the usual page-logic workflow, which makes DomValidation a natural fit.
use GT\Dom\HTMLDocument;
use GT\DomValidation\ValidationException;
use GT\DomValidation\Validator;
use GT\Input\Input;
function do_submit(
HTMLDocument $document,
Input $input,
):void {
$form = $document->querySelector("#example-form");
$validator = new Validator();
try {
$validator->validate($form, $input);
}
catch(ValidationException) {
foreach($validator->getLastErrorList() as $name => $message) {
$field = $form->querySelector("[name='$name']");
$field?->parentElement?->dataset->validationError = $message;
}
return;
}
// Continue with the valid submission.
}Once validation fails, return early.
That keeps the code simple and avoids accidentally continuing with invalid data.
catch(ValidationException) {
// display errors...
return;
}Once the basic flow is clear, continue with Working with input data to see how field names and submitted values are matched.
DomValidation is a separately maintained component of PHP.GT WebEngine.