Validate
As a rule of thumb, you should never trust data that comes from the request. Almost everything that supplied by end-users must be validated in some or another way, if you want to build a secure system. Krystal's validation component would help you to manage validation rules for input fields.
Getting started
Validation should be done only in controllers. Controllers do instantiate a validation service and determine whether user's data looks valid. Then depending on that, you either return error messages or do the upcoming thing, such as inserting or updating a record.
Validation component has only one service, which is called validatorFactory
and is available as a property in controllers. To instantiate a validator, you have to call build()
on it providing configuration.
As an example of typical initialization, it might look like so:
$formValidator = $this->validatorFactory->build(array(
'input' => array(
'source' => $this->request->getPost(),
'definition' => array(
'...field...' => '...rules...'
)
)
));
Let's de-construct that step by step.
- First of all, we define a target input in
input -> source
, which is a copy of $_POST - Second in
input -> definition
we define a target key in the source we specified and attach validation rules on it.
Now let's learn how to defile validation rules.
Configuration
The configuration stored under validator
component. It has only two options : render
and translate
. The render
option a strategy for returning error messages by getErrors()
method. Here's a list of all available renderers:
MessagesOnly
Returns array of error messages.
Standard
Returns an array with field names and their associated error messages.
StandardJson
Does exactly what Standard
, but converts a result-set to JSON string.
JsonCollection
Returns an array with errors messages
and keys
. This can be used to highlight fields that have errors on client-side.
Defining validation rules
A validation rule for a field defines whether a field is optional and its collection of constraints. The required
key specifies whether to run validation on particual field in case it's not empty. For example, when setting requred
to false
, the validation will be runned in case the target field isn't empty. The rules
key defines an array with constraints and their associated options to be applied to that particular input.
For example, suppose you have a simple form, that has only email
field and it looks like this:
<form>
<input type="text" name="email" />
</form>
Typically, for email fields we have two requirements: it must be filled and it must look like as a real email-address. To implement such validation rule, we'd define two built-in constraints NotEmpty
and EmailPattern
.
$formValidator = $this->validatorFactory->build(array(
'input' => array(
'source' => $this->request->getPost(),
'definition' => array(
'email' => array(
'required' => true,
'rules' => array(
'NotEmpty' => array(
'message' => 'Email cannot be blank'
),
'EmailPattern' => array(
'message' => 'Invalid email format'
)
)
)
)
)
));
After instantiating the validation service, you would usually want to run validation process itself. And if it fails, you would want to retrieve error messages. To do so, the validation service has two methods: isValid()
and getErrors()
if ($formValidator->isValid()) {
// Do the rest
} else {
// Fail and return error messages
return $formValidator->getErrors();
}
Input constrains
In case a constraint has parameters, they must be defined as array in value
section. In case there's only one parameter, you can define it as a value itself. For example, for Between
constraint the definition might look so:
'value' => array(1, 10)
For RegExMatch
constraint, that might look so:
'value' => '~(.*)~'
Between
Checks whether numeric value is in range between specified values.
Parameters: First value is a starting range. Second value is an ending range.
Boolean
Checks whether provided value looks as a boolean. Non-empty values, true
, '1' are considered as true.
Callable
Checks whether provider string value can be considered as PHP callable. For example, that can be a function name, or a class method in a format like Class::method
.
CAPTCHA
Validates CAPTCHA's response.
Parameters: Requires CAPTCHA service.
Charset
Checks whether provided charset is supported by current PHP environment.
Contains
Checks whether string contains a character defined in collection.
Parameters: A string that represents a character to be matched. Or an array of such string.
DateFormat
Checks whether string looks as a date format.
DateFormatMatch
Checks whether string matches a particular date format.
Parameters: Date format, or an array of date formats.
Day
Checks whether string value is less than 31.
DirectoryPath
Checks whether string value is a path to a directory.
Domain
Checks whether value looks like as a domain.
EmailPattern
Checks whether a string looks like as email address.
Empty
Checks whether string is empty.
EndsWith
Checks whether string ends with a value.
Parameters: The value to be checked at the end itself.
Even
Checks whether numeric string is even.
Extension
Checks whether string contains an extension.
Parameters: The extension itself without a dot.
FilePath
Checks whether value points to a file path on the file-system.
FileReadable
Checks whether value points to a file path, which is readable.
FileSize
Checks whether file size is expected
Parameters: File size in bytes
Float
Checks whether value is float.
GreaterThan
Checks whether value is greater than.
Parameters: The value to be compared against.
Identity
Checks whether values are identical.
Parameters: Target value to be compared.
InCollection
Checks whether a value in collection (i.e belongs to particular set of values).
Parameters: The array of values itself (i.e the collection)
Integer
Checks whether value is an integer.
IpPattern
Checks whether value looks as IP address.
Json
Checks whether value represents JSON string.
LessOrEqual
Checks whether value is less than or equals.
Parameters: The target value to be compared.
LessThan
Checks whether value is less than.
Lowercase
Checks whether a value is lower-cased.
MacAddress
Checks whether value looks as a MAC-address.
MaxLength
Checks the maximal length of a value.
Parameters
The maximal length.
MinLength
Checks the minimal length of a value.
Parameters
The minimal length.
Negative
Checks whether a value is negative.
NoChar
Checks whether a value doesn't contain a character.
Parameters: An array of characters or a character string to be matched against a value.
NoTags
Checks whether a string hasn't HTML tags.
Parameters: An optional array of allowed tag names (like a
, h1
, etc).
NotEmpty
Checks whether a value isn't empty.
Numeric
Checks whether a value is numeric.
Odd
Checks whether a value is odd.
Positive
Checks whether a value is positive.
RegEx
Checks whether regular expression is valid.
RegExMatch
Checks whether a value matches regular expression.
Parameters: Regular expression to be matched against a value.
Serialized
Checks whether a value has been serialized.
Parameters: Serialization adapter. To learn more, refer to Serialization component.
StartsWith
Checks whether a value starts with a character.
Parameters: The character itself.
Timestamp
Checks whether a value looks as a UNIX-timestamp.
Uppercase
Checks whether a value is upper-cased.
UrlPattern
Checks whether a value looks as URL.
XDigit
Checks whether a value is like XDigit.
Year
Checks whether a value looks like a year.
Validating files
Sometimes in your forms, you might have a file
input that lets your users to upload files. In case you expect users to upload a photo, then you would want to make sure that they selected an image, not a document or malicious php-script. To validate files, you'd simply append new file
input. Its configuration is defined in exactly way as in input
.
$formValidator = $this->validatorFactory->build(array(
'input' => array(
'source' => $this->request->getPost(),
'definition' => array(
'...field...' => '...rules...'
)
),
'file' => array( // <- Append this new file input
'source' => $this->request->getFiles(),
'definition' => array(
'...field...' => '...rules...'
)
)
));
Files constraints
Extension
Check whether files have a valid extension.
Parameters: An array of valid extension (without dots)
FilenameMaxLength
Checks the legth of uploaded file names.
Parameters: The optional length, which is 255 by default.
FilenameRegEx
Validates file names by RegEx pattern.
Parameters: The RegEx pattern
FileSize
Validates whether uploaded files exceed defined allowed filesize.
Parameters: The maximal allowed value, the operator to be applied when doing comparison.
FormSize
Validates whether uploaded files exceed MAX_FILE_SIZE directive defined in a form.
IniSize
Validates whether uploaded files exceed upload_max_filesize
directive in php.ini
IsUploadedFile
Validates whether uploaded files have been uploaded natively via user's form.
NotEmpty
Checks whether at least file has been uploaded.
Partial
Checks whether a file has been uploaded partially.
TmpDir
Checks whether a file can't be uploaded due to missing temporary directory.
Type
Checks whether MIME-Type of uploaded files matches to expected one.
Parameters: The expected mime-type.
UploadAmount
Restricts uploaded files not to exceed defined amount.
Parameters: The desired amount.
WriteFail
Checks whether uploaded files have written to disk successfully.
Validation patterns
If you develop large application, you'd soon note how much duplicated rules you have. For example, in several places you might have rules for title
field, that are completely identical. In order to reduce duplication in validation rules and make them reusable, you can use validation patterns. Validation patterns are represented via an object that internally returns an array of definitions.
So instead, of writing rules like so.
'definition' => array(
'...field...' => '...rules...'
)
you can now write patterned rules like so:
'definition' => array(
'...field...' => new Pattern\SomePattern()
)
In order to attach a pattern, you need to import a base namespace.
use Krystal\Validate\Pattern; // <- Add this right after namespace declaration
and then you can use it like this:
'definition' => array(
'email' => new Pattern\Email(),
// ...
)
where Email
is just an example of built-in pattern.
Available patterns
Here is a complete list of available patterns.
- Address (checks whether address isn't empty and hasn't HTML tags)
- Captcha (checks whether CAPTCHA is valid)
- Comment (checks whether a string hasn't HTML tags)
- ClassName (checks whether class name isn't empty and hasn't HTML tags)
- Content (checks whether content isn't empty)
- Currency (checks whether currency isn't empty and hasn't HTML tags)
- DateFormat (checks whether supplied date format is valid. As a first argument it accepts the format itself)
- Description (checks whether description isn't empty)
- Email (checks whether email isn't empty and it looks as a valid one)
- File (append all generic constraints to a file)
- FullText (checks whether full description isn't empty)
- Height (check whether height is numeric and not empty)
- ImageFile (checks whether selected file looks as valid image)
- ImageHeight (checks whether image height is numeric and not empty)
- ImageQuality (checks whether image quality is numeric, is not empty and its range between 1 and 100)
- ImageWidth (checks whether image width is numeric and is not empty)
- IntroText (checks whether introduction text isn't empty)
- LanguageCode (checks whether language code isn't empty)
- Login (checks whether login isn't empty and hasn't HTML tags)
- Message (checks whether message isn't empty and hasn't HTML tags)
- Name (checks whether name isn't empty and hasn't HTML tags)
- Order (checks whether order isn't empty, is numeric and greater than 0)
- Password (checks whether password isn't empty)
- PasswordConfirmation (checks whether passwords are identical. As a first argument it accepts a password)
- PerPageCount (checks whether value is numeric, isn't empty and greater than 0)
- Phone (checks whether a value isn't empty and matches a pattern)
- Price (checks whether a value isn't empty, is numeric and greater than 0)
- Query (checks whether a value isn't empty and greater than 3)
- TemplateName (checks whether a value isn't empty and contains only English letters)
- ThemeName (the same as TemplateName, but has different messages)
- ThumbHeight, ThumbWidth (check whether a value isn't empty and greater than 0)
- Title (checks whether a value isn't empty and hasn't HTML tags)
- Url (checks whether a value looks as URL)
- Username (checks whether a value isn't empty and its length is between 3 and 15 and it hasn't HTML tags)
- Width (checks whether a value isn't empty, is numeric and its greater than 1)