Input Validation

\Lia\Utility\InputValidator performs rules-based validations and can typecast in some cases (such as string to int). \Lia\Addon\POSTValidator integrates InputValidator with Liaison, removing all $_POST entries when activated, then re-populating them ONLY when validated. POSTValidator can be activated globally, on a per-Package basis, or you can use a custom Hook for more granular control of its activation.

Related: Forms, POSTValidator, InputValidator, Validator Tests, Hooks

Docs

  • Validation Rules
  • POST Validator Usage
  • Input Validator Usage
  • Activate POST Validator

Validation Rules

InputValidator.php defines methods like is_{rulename}. Each rulename is a builtin rule.

Note: See Input Validator Usage and POST Validator Usage below to add custom rules.

Built-in Rules:

  • string: $value must be a string per is_string($value)
  • number: $value must be a number per is_numeric($value)
  • int: $value must be an int. Typecasts to int if value is a string containing int.
  • alnum: $value must be alphanumeric, per ctype_alnum($value)
  • oneof: $value must be in the $target_values list. $target_values are comma separated
  • maxlen: $value must be a string longer than $length
  • minval: $value must be >= $intval
  • nohtml: (UNTESTED) $value must not contain html or htmlspecialchars. If you pass 'strip', then strip_tags() & htmlspecialchars() will modify value.
  • safehtml: (UNTESTED) $value must only contain safe html tags. If you pass 'strip', then value is set to strip_tags($value, ALLOWED_TAGS). (no script or style. See function definition for full list)

POST Validator Usage

For additional validation examples, see Input Validator Usage below. The rules-format is the same for both, though POSTValidator::validate() is a different method signature from InputValidator::validate().

Example:
$_POST['blog_title'] and $_POST['blog_id'] and $_POST['status'] and $_POST['body'] were submitted.

<?php  
  
$pv = \Lia\Addon\POSTValidator::from($lia);  
// $pv->validator->add_rule(...);  
  
$pv->validate($post_key, ?$rules, ?$validation_function);  
  
// Both the rules list AND the custom validation function must pass  
$no_obscene_words = function(string $key, mixed $value): bool { return true; };  
$pv->validate('blog_title', 'string|minlen:20|maxlen:120|nohtml', $no_obscene_words);  
  
$pv->validate('blog_id', 'int');  
  
$no_javascript = //custom function  
$pv->validate('body', 'string|maxlen:5000|minlen:150', $no_javascript);  
  
  
// Rule with multiple options  
$pv->validate('status', 'oneof:draft,public,archive', "public");  // returns true;  

Input Validator Usage

The input validator can be used directly, through its validate() method (recommended) or by calling its built-in rules directly.

The validator is intended for use with form submissions, so values are expected to be strings. They are not required to be strings, but they usually will be, so strings are used in all examples.

Built-in Validation:

<?php  
  
$v = new \Lia\Utility\InputValidator();  
  
// returns bool true/false. $name_of_input is not used by any built-in rules.  
$v->validate($rules_list, $value_to_validate, ?$name_of_input, ?&$reference);  
  
// Single rule  
$v->validate('int', "37");  
// Multiple Rules: you can use as many as you like, separated by a bar (|)  
$v->validate('int|minval:15', "12"); // this would return false, since 12 smaller than 15  
// Typecasting: such as a number being submitted via a form  
$v->validate('int', "93", null, $ref); // returns true & sets $ref=93  
// Rule with multiple options  
$v->validate('oneof:a,b,c', "b"); // returns true;  
  
  
// Built-in validation rules are methods on InputValidator in the format: `is_RULENAME()`  
$v->is_int("abc"); // false  
$v->is_int("17"); // true  
  
// Rules can be passed as an array  
$v->validate(  
    [ 'int', // 'int'=>null is also acceptable  
      'oneof' => '1,2,3' ],  
    "3"  
); // returns true  

Adding Rules:

<?php  
  
$v = \Lia\Addon\POSTValidator::from($lia)->validator;  
// or $v = new \Lia\Utility\InputValidator();  
  
//$v->add_rule(string $rule_name, callable $callable, bool $overwrite_existing = false)  
  
// To prevent conflicts from other packages, you may wish to use namespaces like: 'taeluf.strong_password'  
$v->add_rule('strong_password',   
    function(mixed $password, string $name_of_input, string $rule_name, ?mixed $rule_options): bool {  
        if (strlen($password) < 9093)return false;  
        if (!\YourNamespace\string_contains_symbols($password))return false;  
        if (!preg_match('/[A-Z]/', $password)) return false;  
  
        return true;  
    }  
);  
  
$v->validate('strong_password', 'I love bears'); // this will fail because no symbols!  

Activate POST Validator

When activated, \Lia\Addon\POSTValidator sets $_POST = []. As values are validated, $_POST is re-populated.

<?php  
  
// recommended, activates during ROUTES_FILTERED hook only if the given package is being requested.  
\Lia\Addon\POSTValidator::activateForPackage(\Lia\Package $package);  
  
// Activates immediately and affects all requests  
\Lia\Addon\POSTValidator::activate(\Lia $lia);  
  
// CUSTOM activation, example taken from POSTValidator::activateForPackage()  
\Lia\Addon\Hook::from($package->lia)  
    ->add(\Lia\Hooks::ROUTES_FILTERED,   
        function(\Lia\Obj\Route $route) use ($package): void {  
            if ($route->package() != $package)return;  
            static::activate($package->lia);  
        }  
    );