sandromiguel/verum-php

Server-Side Form Validation Library for PHP


README

Verum PHP

License Latest Stable Version Dependents

Verum PHP

Verum PHP is a server-side validation library for PHP that allows you to validate arrays (with file support) with ease. It comes with custom error messages, rules, built-in translations, and zero dependencies.

Server-Side Validation Library for PHP

  • Validate arrays (with file support)
  • Custom error messages
  • Custom rules
  • Built-in translations
  • Zero dependencies

Table of Contents

  1. Getting Started
  2. Usage
  3. Custom validations
  4. Available Rules
  5. Contributing
  6. Questions
  7. License

Getting Started

Installation

Install Verum PHP with Composer

composer require sandromiguel/verum-php

Usage

Simple usage example

Validate a simple registration form (name, email and age)

use Verum\Validator;

$rules = [
    'name' => [
        'rules' => [
            'required',
        ],
    ],
    'email' => [
        'rules' => [
            'required',
            'email',
        ],
    ],
    'age' => [
        'rules' => [
            'numeric',
        ],
    ],
];

$validator = new Validator($_POST, $rules);

echo json_encode(
    [
        'valid'  => $validator->validate(),
        'errors' => $validator->getErrors(),
    ]
);
Valid form example

Input:

[
    'name' => 'John Doe',
    'email' => 'johndoe@example.com',
    'age' => '20',
]

Output:

{
    "valid": true,
    "errors": []
}
Invalid form example

Input:

[
    'name' => '',
    'email' => 'some text',
    'age' => 'some text',
]

Output:

{
    "valid": false,
    "errors": {
        "name": {
            "label": null,
            "rules": {
                "required": "This field is required."
            }
        },
        "email": {
            "label": null,
            "rules": {
                "email": "This field must be a valid email address."
            }
        },
        "age": {
            "label": null,
            "rules": {
                "numeric": "This field must be numeric."
            }
        }
    }
}

Use RuleEnum class

You can use the RuleEnum class to access all rule names.

use Verum\Validator;
use Verum\Enum\RuleEnum;

$rules = [
    'name' => [
        'rules' => [
            RuleEnum::REQUIRED,
        ],
    ],
    ...
];

Specify the fields label (naming inputs)

$rules = [
    'name' => [
        'label' => 'Name',
        'rules' => [
            RuleEnum::REQUIRED,
        ],
    ],
    ...
];

Output:

{
    ...
    "errors": {
        "name": {
            "label": "Name",
            "rules": {
                "required": 'The "Name" field is required.'
            }
        },
        ...
    }
}

Specify field labels for each language

$rules = [
    'name' => [
        'label' => [
            'en' => 'Name',
            'pt-pt' => 'Nome',
        ],
        'rules' => [
            RuleEnum::REQUIRED,
        ],
    ],
    ...
];

Output (pt-pt):

{
    ...
    "errors": {
        "name": {
            "label": "Nome",
            "rules": {
                "required": 'O campo "Nome" é obrigatório.'
            }
        },
        ...
    }
}

Specify the messages language

You can use some built-in translations:

  • 'en' -> English (default)
  • 'nl-nl' -> Dutch
  • 'pt-pt' -> Portuguese-Portugal
  • 'pt-br' -> Portuguese-Brazil
$validator = new Validator($_POST, $rules, 'pt-pt');

Specify the messages language using the LangEnum class

use Verum\Validator;
use Verum\Enum\LangEnum;

...

$validator = new Validator($_POST, $rules, LangEnum::PT_PT);

Specify a custom error message

  • Useful to override the default error message.
  • Useful for localization.
...
$validator = new Validator($_POST, $rules);
$validator->addSimpleCustomMessage('min_length', 'Min Length rule custom error message');
...

Output example:

{
    ...
    "errors": {
        "name": {
            "label": "Name",
            "rules": {
                "min_length": "Min Length rule custom error message"
            }
        },
        ...
    }
}

Specify a custom error message with placeholders

...
$validator = new Validator($_POST, $rules);
$validator->addSimpleCustomMessage('min_length', 'Number of characters detected: {param:1}. Field name: "{param:2}".');
...

Output example:

{
    ...
    "errors": {
        "name": {
            "label": "Name",
            "rules": {
                "min_length": 'Number of characters detected: 5. Field name: "Name".'
            }
        },
        ...
    }
}

Specify a custom error message for fields with and without a label

...
$validator = new Validator($_POST, $rules);
$validator->addCustomMessage(
    'required',
    'Custom error message with label for required rule. Label: {param:1}.',
    'Custom error message without label for required rule.'
);
...

Output - Field with label:

{
    ...
    "errors": {
        "name": {
            "label": "Name",
            "rules": {
                "required": 'Custom error message with label for required rule. Label: Name.'
            }
        },
        ...
    }
}

Output - Field without label:

{
    ...
    "errors": {
        "name": {
            "label": null,
            "rules": {
                "required": "Custom error message without label for required rule."
            }
        },
        ...
    }
}

Specify multiple custom error messages at once

...
$validator = new Validator($_POST, $rules);
$validator->addCustomMessages(
    [
        'min_length' => 'Custom message for the "min_length" rule.',
        'required' => 'Custom message for the "required" rule.',
        // other messages ...
    ]
);
...

Specify multiple custom error messages at once for fields with and without a label

...
$validator = new Validator($_POST, $rules);
$validator->addCustomMessages(
    [
        'numeric' => [
            'withLabel' => 'Custom message with label for "numeric" rule. Label: {param:1}.',
            'withoutLabel' => 'Custom message without label for "numeric" rule.',
        ],
        'min_length' => [
            'withLabel' => 'Custom message with label for "min_length" rule. Label: {param:2}, value: {param:1}.',
            'withoutLabel' => 'Custom message without label for "min_length" rule. Value: {param:1}.',
        ],
        // other messages ...
    ]
);
...

Handling Multi-Name Fields

With Verum PHP, you can handle multi-name fields more effectively. These are fields that include language identifiers or other variations in their names. For example, if you have fields like title.en, title.pt, description.en, and description.pt, you can specify rules for them using wildcards.

$rules = [
    'title.*' => [
        'rules' => [
            RuleEnum::REQUIRED,
        ],
    ],
    'description.*' => [
        'rules' => [
            RuleEnum::REQUIRED,
            RuleEnum::MIN_LENGTH => 10,
        ],
    ],
];

$validator = new Validator($_POST, $rules);
// ...

Output example:

{
    "valid": false,
    "errors": {
        "title.en": {
            "label": null,
            "rules": {
                "required": "This field is required."
            }
        },
        "title.pt": {
            "label": null,
            "rules": {
                "required": "This field is required."
            }
        },
        "description.en": {
            "label": null,
            "rules": {
                "required": "This field is required.",
                "min_length": "This field must be at least 10 characters long."
            }
        },
        "description.pt": {
            "label": null,
            "rules": {
                "required": "This field is required.",
                "min_length": "This field must be at least 10 characters long."
            }
        }
    }
}

Custom validations

You can use your custom validations and inject the error message.

if ($myCustomValidationFail) {
    $validator->addError(
        'someFieldName',
        'Some field name',
        ['no_duplicate' => 'A user already exists with that username')]
    );
    // ...
}

Available Rules

  1. alpha
  2. alpha_numeric
  3. between
  4. between_length
  5. boolean_value
  6. contains
  7. date
  8. email
  9. equals
  10. file_max_size
  11. file_mime_type
  12. float_number
  13. image_max_height
  14. image_max_width
  15. image_min_height
  16. image_min_width
  17. integer
  18. ip
  19. ipv4
  20. ipv6
  21. max
  22. max_length
  23. min
  24. min_length
  25. numeric
  26. regex
  27. required
  28. slug
  29. url

alpha

Checks whether the value contains only alphabetic characters.

$rules = [
    'nickname' => [
        'label' => 'Nickname',
        'rules' => [
            RuleEnum::ALPHA,
        ],
    ],
];
Value alpha alpha + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text' ✔️ ✔️
'text with spaces'

alpha_numeric

Checks whether the value contains only alphanumeric characters.

$rules = [
    'nickname' => [
        'label' => 'Nickname',
        'rules' => [
            RuleEnum::ALPHA_NUMERIC,
        ],
    ],
];
Value alpha_numeric alpha_numeric + required
null ✔️
'' ✔️
'0' ✔️ ✔️
0 ✔️ ✔️
false
[]
-1
1 ✔️ ✔️
true
'text' ✔️ ✔️
'text with spaces'

between

Checks whether the value is between two values.

$rules = [
    'age' => [
        'label' => 'Age',
        'rules' => [
            RuleEnum::BETWEEN => [12, 29],
        ],
    ],
];
Value between [1, 10] between [1, 10] + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1 ✔️ ✔️
true
'some text'

between_length

Checks whether the number of characters of the value is between min and max values.

$rules = [
    'nickname' => [
        'label' => 'Nickname',
        'rules' => [
            RuleEnum::BETWEEN_LENGTH => [3, 15],
        ],
    ],
];
Value between_length [5,25] between_length [5,25] + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
12345 ✔️ ✔️
true
'text'
'text with 23 characters' ✔️ ✔️

boolean_value

Checks whether the value is a boolean value. Returns true for 1/0, '1'/'0', 'on'/'off', 'yes'/'no', true/false.

$rules = [
    'light' => [
        'label' => 'Light',
        'rules' => [
            RuleEnum::BOOLEAN_VALUE,
        ],
    ],
];
Value boolean_value boolean_value + required
null ✔️
'' ✔️
'0' ✔️ ✔️
0 ✔️ ✔️
false ✔️ ✔️
[]
-1
'1' ✔️ ✔️
1 ✔️ ✔️
true ✔️ ✔️
'text'
'on' ✔️ ✔️
'off' ✔️ ✔️
'yes' ✔️ ✔️
'no' ✔️ ✔️

contains

Checks whether the value is in an array.

$rules = [
    'priority' => [
        'label' => 'Priority',
        'rules' => [
            RuleEnum::CONTAINS => ['low', 'high'],
        ],
    ],
];
Value contains ['low','high'] contains ['low','high'] + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'low' ✔️ ✔️
'high' ✔️ ✔️

date

Checks whether the value is a valid date (Y-m-d) or a custom format.

Default format (Y-m-d)

$rules = [
    'dob' => [
        'label' => 'Date of birth',
        'rules' => [
            RuleEnum::DATE,
        ],
    ],
];

Custom format (e.g. d.m.Y)

$rules = [
    'dob' => [
        'label' => 'Date of birth',
        'rules' => [
            RuleEnum::DATE => ['d.m.Y'],
        ],
    ],
];
Value date [Y-m-d] date [Y-m-d] + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'2020-09-30' ✔️ ✔️

email

Checks whether the value has a valid email format.

$rules = [
    'email' => [
        'label' => 'Email',
        'rules' => [
            RuleEnum::EMAIL,
        ],
    ],
];
Value email email + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'john@example.com' ✔️ ✔️

equals

Checks whether the value is equal to another.

$rules = [
    'repeat_password' => [
        'label' => 'Repeat Password',
        'rules' => [
            RuleEnum::EQUALS => ['password'],
        ],
    ],
];

Comparison with 'text'

Value equals equals + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text' ✔️ ✔️
'another text'

file_max_size

Checks whether the file size does not exceed a given value.

Enter a value in bytes.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::FILE_MAX_SIZE => [102400],
        ],
    ],
];

Comparison with 102400 bytes

Value file_max_size file_max_size + required
null ✔️
50000 ✔️ ✔️
150000

file_mime_type

Checks whether the file type is allowed.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::FILE_MIME_TYPE => ['image/png', 'image/jpeg'],
        ],
    ],
];
Value file_mime_type file_mime_type + required
null ✔️
image/png ✔️ ✔️
text/plain

float_number

Checks whether the value is a floating point number.

$rules = [
    'price' => [
        'label' => 'Price',
        'rules' => [
            RuleEnum::FLOAT_NUMBER,
        ],
    ],
];
Value float_number float_number + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
12345
123.45 ✔️ ✔️
true
'text'
'text with spaces'

image_max_height

Checks whether the image height does not exceed a given value.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::IMAGE_MAX_HEIGHT => [600],
        ],
    ],
];
Value image_max_height image_max_height + required
null ✔️
500px ✔️ ✔️
1000px

image_max_width

Checks whether the image width does not exceed a given value.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::IMAGE_MAX_WIDTH => [1000],
        ],
    ],
];
Value image_max_width image_max_width + required
null ✔️
500px ✔️ ✔️
1500px

image_min_height

Checks whether the image height is not less than a given value.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::IMAGE_MIN_HEIGHT => [300],
        ],
    ],
];
Value image_min_height image_min_height + required
null ✔️
100px
500px ✔️ ✔️

image_min_width

Checks whether the image width is not less than a given value.

$rules = [
    'profile_photo' => [
        'label' => 'Profile Photo',
        'rules' => [
            RuleEnum::IMAGE_MIN_WIDTH => [500],
        ],
    ],
];
Value image_min_width image_min_width + required
null ✔️
400px
600px ✔️ ✔️

integer

Checks whether the value is integer.

$rules = [
    'distance' => [
        'label' => 'Distance',
        'rules' => [
            RuleEnum::INTEGER,
        ],
    ],
];
Value numeric numeric + required
null ✔️
'' ✔️
'0'
0 ✔️ ✔️
false
[]
-1 ✔️ ✔️
1 ✔️ ✔️
true
'text'

ip

Checks whether the value is a valid IP address.

$rules = [
    'ip' => [
        'label' => 'IP',
        'rules' => [
            RuleEnum::IP,
        ],
    ],
];
Value ip ip + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'10.10.10.10' ✔️ ✔️
'2607:f0d0:1002:51::4' ✔️ ✔️

ipv4

Checks whether the value is a valid IPv4 address.

$rules = [
    'ipv4' => [
        'label' => 'IPv4',
        'rules' => [
            RuleEnum::IPV4,
        ],
    ],
];
Value ipv4 ipv4 + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'10.10.10.10' ✔️ ✔️
'2607:f0d0:1002:51::4'

ipv6

Checks whether the value is a valid IPv6 address.

$rules = [
    'ipv6' => [
        'label' => 'IPv6',
        'rules' => [
            RuleEnum::IPV6,
        ],
    ],
];
Value ipv6 ipv6 + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'10.10.10.10'
'2607:f0d0:1002:51::4' ✔️ ✔️

max

Checks whether the value does not exceed a given value.

$rules = [
    'people' => [
        'label' => 'People',
        'rules' => [
            RuleEnum::MAX => [5],
        ],
    ],
];
Value max max + required
null ✔️
'' ✔️
'0' ✔️ ✔️
0 ✔️ ✔️
false
[]
-1 ✔️ ✔️
1 ✔️ ✔️
true
'text'
12345
'12345'

max_length

Checks whether the number of characters of the value does not exceed a given value.

$rules = [
    'nickname' => [
        'label' => 'Nickname',
        'rules' => [
            RuleEnum::MAX_LENGTH => [2],
        ],
    ],
];
Value max_length max_length + required
null ✔️
'' ✔️
'0' ✔️ ✔️
0 ✔️ ✔️
false ✔️ ✔️
[]
-1 ✔️ ✔️
1 ✔️ ✔️
true ✔️ ✔️
'text'
12345
'12345'

min

Checks whether the value is not less than a given value.

$rules = [
    'people' => [
        'label' => 'People',
        'rules' => [
            RuleEnum::MIN => [2],
        ],
    ],
];
Value min min + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
12345 ✔️ ✔️
'12345' ✔️ ✔️

min_length

Checks whether the number of characters of the value is not less than a given value.

$rules = [
    'nickname' => [
        'label' => 'Nickname',
        'rules' => [
            RuleEnum::MIN_LENGTH => [2],
        ],
    ],
];
Value max_length max_length + required
null ✔️
''
'0'
0
false
[]
-1 ✔️ ✔️
1
true
'text' ✔️ ✔️
12345 ✔️ ✔️
'12345' ✔️ ✔️

numeric

Checks whether the value is numeric.

$rules = [
    'age' => [
        'label' => 'Age',
        'rules' => [
            RuleEnum::NUMERIC,
        ],
    ],
];
Value numeric numeric + required
null ✔️
'' ✔️
'0' ✔️ ✔️
0 ✔️ ✔️
false
[]
-1 ✔️ ✔️
1 ✔️ ✔️
true
'text'

regex

Checks whether the value matches a given regular expression.

$rules = [
    'path' => [
        'label' => 'Path',
        'rules' => [
            RuleEnum::REGEX => ['/\/client\/[0-9a-f]+$/'],
        ],
    ],
];

Validation with the '/\/client\/[0-9a-f]+$/' pattern

Value regex regex + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'/client/77c9e105d1f548b29958f0512967de87' ✔️ ✔️
'/client/invalid-uuid'

required

Checks whether the value is not empty.

$rules = [
    'name' => [
        'label' => 'Name',
        'rules' => [
            RuleEnum::REQUIRED,
        ],
    ],
];
Value required
null
''
'0' ✔️
0 ✔️
false ✔️
[]
-1 ✔️
1 ✔️
true ✔️
'some text' ✔️

slug

Checks whether the value is a valid Slug (e.g. hello-world_123).

$rules = [
    'slug' => [
        'label' => 'Slug',
        'rules' => [
            RuleEnum::SLUG,
        ],
    ],
];
Value slug slug + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text' ✔️ ✔️
'text with spaces'
'hello-world_123' ✔️ ✔️

url

Checks whether the value is a valid URL.

$rules = [
    'url' => [
        'label' => 'URL',
        'rules' => [
            RuleEnum::URL,
        ],
    ],
];
Value url url + required
null ✔️
'' ✔️
'0'
0
false
[]
-1
1
true
'text'
'http://www.some-domain.com' ✔️ ✔️

Contributing

Want to contribute? All contributions are welcome. Read the contributing guide.

Questions

If you have questions tweet me at @sandro_m_m or open an issue.

License

This project is licensed under the MIT License - see the LICENSE file for details

**~ sharing is caring ~**