Умалишенный validation php. Класс Validator для валидации POST данных. Определение собственного класса

Validation of data is a fundamentally important aspect of a CRUD application. You need to be sure that the data that the client is sending you is what you expect. This is not just for security reasons, protecting your data from misuse and intentional corruption, but also simply from unintentional mistakes in submitting data. Strings limited to a certain length, dates in a particular format and required fields are all common uses of data validation.

The Editor PHP libraries provide two different validation methods:

  • Field based, where each individual value submitted is independently validated: Field->validator() .
  • Global validation, where the data submitted by the client-side can be validated as a whole: Editor->validator() .
Legacy information (v1.6-)

Please note that PHP validation in Editor 1.6 and older was a little different. The older form of validation will still work with the 1.7+ libraries and its documentation remains available , but for new projects use the validation style discussed here.

Field validation is the one you will most commonly work with - for example checking that an e-mail address field actually contains an e-mail address, and Editor provides a number of ready to use validators for the most common data types as well as the ability to specify your own. Global validation can be useful when checking dependencies between fields and conflicts in the existing data set.

Field validation

The Editor PHP libraries provide a validator() method for the Field class and a number of pre-built validation methods in the Validate class. Each of these validation methods returns a function which is executed when required to validate submitted data.

Consider the following example - the Validate::minNum() function is configured with a number and returns a function that can be used for the field validator.

Field::inst("age") ->validator(Validate::minNum(16));

Please see below for more detailed examples.

Validation options

Each validation method provided by the Validation class can optionally accept parameters to tell it how to validate data (for example the minLen method will accept an integer to indicate the minimum length of an acceptable string), but all optionally accept a ValidateOptions class instance. This class defines a number of options that are shared between all validation methods.

The ValidateOptions class is constructed with ValidateOptions::inst() (or new ValidateOptions() in PHP 5.4+) similar to the other Editor classes. It has three methods that can be used to alter the validation behaviour:

  • ->allowEmpty(boolean) : How to handle empty data (i.e. a zero length string):
    • true (default) - Allow the input for the field to be zero length
    • false - Disallow zero length inputs
  • ->message(string) : the error message to show if the validation fails. This is simply "Input not valid" by default, so you will likely want to customise this to suit your needs.
  • ->optional(boolean) : Require the field to be submitted or not. This option can be particularly useful in Editor as Editor will not set a value for fields which have not been submitted - giving the ability to submit just a partial list of options.
    • true (default) - The field does not need to be be in the list of parameters sent by the client.
    • false - The field must be included in the data submitted by the client.
Example - setting a custom error message Field::inst("stock_name") ->validator(Validate::minNum(10, new ValidateOptions::inst() ->message("Stock name must be at least 10 characters long"))); Multiple validators

It can often be useful to use multiple validators together, for example to confirm that an input string is less than a certain number of characters and also that it is unique in the database. Multiple validators can be added to a field simply by calling the Field->validator() method multiple times. Rather than overwriting the previous validator it will in fact add them together. They are run in the sequence they were added, and all validators must pass for the data to be accepted as valid.

As an example consider the following code which will check the min and max length of the data, and also that it is unique:

Field::inst("stock_name") ->validator(Validate::minLen(10)) ->validator(Validate::maxLen(12)) ->validator(Validate::unique());

Ready to use field validators

The Validate class in the Editor PHP libraries has a number of methods which can be used to perform validation very quickly and easily. These are:

Basic
  • none(ValidateOptions $cfg=null) - No validation is performed
  • basic(ValidateOptions $cfg=null) - Basic validation - only the validation provided by ValidateOptions is performed
  • required(ValidateOptions $cfg=null) - The field must be submitted and the data must not be zero length. Note that Editor has the option of not submitting all fields (for example when inline editing), so the notEmpty() validator is recommended over this one.
  • notEmpty(ValidateOptions $cfg=null) - The field need not be submitted, but if it is, it cannot contain zero length data
  • boolean(ValidateOptions $cfg=null) - Check that boolean data was submitted (including 1, true on, yes, 0, false, off and no)
Numbers
  • numeric(string $decimalChar=".", ValidateOptions $cfg=null) - Check that any input is numeric.
  • minNum(integer $min, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is greater than or equal to the given number
  • maxNum(integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is less than or equal to the given number
  • minMaxNum(integer $min, integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is within the given range (inclusive)
Strings
  • email(ValidateOptions $cfg=null) - Validate an input as an e-mail address.
  • ip(ValidateOptions $cfg=null) - Validate as an IP address.
  • minLen(integer $min, ValidateOptions $cfg=null) - Validate a string has a minimum length.
  • maxLen(integer $max, ValidateOptions $cfg=null) - Validate a string does not exceed a maximum length.
  • minMaxLen(integer $min, integer $max, ValidateOptions $cfg=null) - Validate a string has a given length in a range
  • noTags(ValidateOptions $cfg=null) - Don"t allow HTML tags
  • url(ValidateOptions $cfg=null) - Validate as an URL address.
  • values(array $values, ValidateOptions $cfg=null) - Allow only values which have been specified in an array of options (the first parameter). This could be useful if you wish to have free-form input or event a select list, and want to confirm that the value submitted is within a given data set (see also the dbValues() method if valid values are stored in a database). Note that the values given in the values array are checked against the submitted data as case-sensitive data (i.e. `"A" != "a").
  • xss(ValidateOptions $cfg=null) - Check to see if the input could contain an XSS attack . This used the Field "s XSS formatting function to determine if the input string needs to be formatted or not.
Date / time
  • dateFormat(string $format, ValidateOptions $cfg=null) - Check that a valid date input is given. The format is defined by PHP"s date() method which is used for the parsing of date and time string.
Database
  • dbValues(ValidateOptions $cfg=null, string $column=null, string $table=null, Database $db=null, array $valid=null) - Allow only a value that is present in a database column. This is specifically designed for use with joined tables (i.e. ensure that the reference row is present before using it), but it could potentially also be used in other situations where referential integrity is required.
  • unique(ValidateOptions $cfg=null, string $column=null, string $table=null, array $db=null) - Ensure that the data submitted is unique in the table"s column.
One-to-many (Mjoin)

Note that these methods are for use with the Mjoin->validator() method (Editor 1.9 and newer). Please see the Mjoin documentation for more details.

  • mjoinMinCount($minimum, ValidateOptions $cfg=null) - Require that at least the given number of options / values are submitted for the one-to-many join.
  • mjoinMaxCount($maximum, ValidateOptions $cfg=null) - Require that this many or less options / values are submitted for the one-to-many join.
Custom field validators

If the provided methods above don"t suit the kind of validation you are looking for, it is absolutely possible to provide custom validation methods. The validator() Field method will accept a function that returns either true or a string and accepts the following input parameters:

  • value - The value to be validated
  • data - The collection of data for the row in question
  • field -The host Field instance
  • host - Information about the host Editor instance
  • The return value should be true to indicate that the validate passed, or a string that contains an error message if the validation failed.

    The following simple example shows how a maxLen string check could be implemented with a custom validation method:

    Field::inst("last_name") ->validator(function ($val, $data, $field, $host) { return strlen($val) > 50 ? "Name length must be 50 characters or less" : true; });

    Field validation examples

    Use the Validation.minNum() method to validate an input as numeric and greater or equal to a given number (no validation options specified, so the defaults are used):

    // Simple non-empty field Field::inst("age") ->validator(Validate::minNum(16))

    As above, but with ValidateOptions used to set the error message:

    // Number range check with custom error message Field::inst("range") ->validator(Validate::minNum(16, ValidateOptions::inst() ->message("Minimum age is 16")));

    This time validating an e-mail address which cannot be empty and must be submitted:

    Field::inst("email") ->validator(Validate::email(ValidateOptions::inst() ->allowEmpty(false) ->optional(false)));

    A join with dbValues which will accept an empty value, which is stored as null on the database:

    Field::inst("users.site") ->options(Options::inst() ->table("sites") ->value("id") ->label("name")) ->validator(Validate::dbValues()),

    Allow only certain values to be submitted:

    Field::inst("group") ->validator(Validate::values(array("CSM", "FTA", "KFVC")))

    The following shows a complete Editor example with validation methods applied:

    Ditor::inst($db, "staff") ->fields(Field::inst("first_name") ->validator(Validate::notEmpty(ValidateOptions::inst() ->message("A first name is required"))), Field::inst("last_name") ->validator(Validate::notEmpty(ValidateOptions::inst() ->message("A last name is required"))), Field::inst("position"), Field::inst("email") ->validator(Validate::email(ValidateOptions::inst() ->message("Please enter an e-mail address"))), Field::inst("office"), Field::inst("extn"), Field::inst("age") ->validator(Validate::numeric()) ->setFormatter(Format::ifEmpty(null)), Field::inst("salary") ->validator(Validate::numeric()) ->setFormatter(Format::ifEmpty(null)), Field::inst("start_date") ->validator(Validate::dateFormat("Y-m-d")) ->getFormatter(Format::dateSqlToFormat("Y-m-d")) ->setFormatter(Format::dateFormatToSql("Y-m-d"))) ->process($_POST) ->json();

    Global validators

    You may also find it useful to be able to define a global validator that will execute whenever a request is made to the server and the Editor->process() method is executed. This method can be used to provide security access restrictions, validate input data as a whole or even to check that a user is logged in before processing the request.

    Function

    The function that is given to the Editor->validator() method has the following signature:

  • $editor - The Editor instance that the function is being executed for.
  • $action - The action being performed - this will be one of:
    • Editor::ACTION_READ - Read / get data
    • Editor::ACTION_CREATE - Create a new record
    • Editor::ACTION_EDIT - Edit existing data
    • Editor::ACTION_DELETE - Delete existing row(s)
    • Editor::ACTION_UPLOAD - Upload a file.
  • $data - The data submitted by the client.
  • The return value from the function should be a string if the validation fails, where the string returned is the error message to show the end user. If the validation passes, return an empty string, null or simply have no return statement.

    Note that this function is executed only once when the Editor->process() method is called, rather than once per submitted row. Also, as of Editor 1.9, it is possible to add multiple validation functions by calling Editor->validator() multiple times, just as with the field validators. The given validators will run sequentially.

    Examples // Allow read only access based on a session variable Editor::inst($db, "table") ->fields(...) ->validator(function ($editor, $action, $data) { if ($action !== Editor::ACTION_READ && $_SESSION["read_only"]) { return "Cannot modify data"; } }) ->process($_POST) ->json(); // Create and edit with dependent validation Editor::inst($db, "table") ->fields(...) ->validator(function ($editor, $action, $data) { if ($action === Editor::ACTION_CREATE || $action === Editor::ACTION_EDIT) { foreach ($data["data"] as $pkey => $values) { if ($values["country"] === "US" && $values["location"] === "London UK") { return "London UK is not in the US"; } } } }) ->process($_POST) ->json(); PHP API documentation

    The PHP API developer documentation for the Editor PHP classes is available for detailed and technical discussion about the methods and classes discussed above.

    При создании веб-приложений важно серьезно относиться к безопасности, особенно, когда приходится иметь дело с получением данных от пользователей.

    Общее правило безопасности - не доверять никому, так что нельзя надеяться на то, что пользователи всегда будут вводить в формы правильные значения. Например, вместо ввода в поле правильного email-адреса, пользователь может ввести неверный адрес, или вообще какие-нибудь вредоносные данные.

    Когда дело доходит до валидации пользовательских данных, ее можно проводить как на стороне клиента (в веб-браузере), так и на серверной стороне.

    Ранее валидацию на стороне клиента можно было провести только с помощью JavaScript. Но все изменилось (или почти изменилось), так как с помощью HTML5 валидацию можно проводить средствами браузера, без необходимости писать сложные скрипты для валидации на JavaScript.

    Валидация форм с помощью HTML5

    HTML5 предоставляет довольно надежный механизм, основанный на следующих атрибутах тега : type , pattern и require . Благодаря этим новым атрибутам вы можете переложить некоторые функции проверки данных на плечи браузера.

    Давайте рассмотрим эти атрибуты, чтобы понять, как они могут помочь в валидации форм.

    Атрибут type

    Этот атрибут говорит, какое поле ввода отобразить для обработки данных, например, уже знакомое поле типа

    Некоторые поля ввода уже предоставляют стандартные способы валидации, без необходимости писать дополнительный код. Например, проверяет поле на то, что введенное значение соответствует шаблону правильного email адреса. Если в поле введен неверный символ, форму нельзя будет отправить, пока значение не будет исправлено.

    Попробуйте поиграться со значениями поля email в нижеприведенной демонстрации .

    Также существуют другие стандартные типы полей, вроде , и для валидации чисел, URL’ов и телефонных номеров соотвествено.

    Замечание: формат телефонного номера различается для разных стран из-за несоответствия количества цифр в телефонных номерах и разности форматов. Как результат, спецификация не определяет алгоритм проверки телефонных номеров, так что на время написания статьи данная возможность слабо поддерживается браузерами.

    К счастью для нас, валидацию телефонных номеров можно провести с использованием атрибута pattern , который принимает как аргумент регулярное выражение, который мы рассмотрим далее.

    Атрибут pattern

    Атрибут pattern , скорее всего, заставит многих фронтенд-разработчиков прыгать от радости. Этот атрибут принимает регулярное выражение (аналогичное формату регулярных выражений JavaScript), по которому будет проверяться корректность введенных в поле данных.

    Регулярные выражения это язык, использующийся для разбора и манипуляции текстом. Они часто используются для сложных операций поиска и замены, а также для проверки корректности введенных данных.

    На сегодняшний день регулярные выражения включены в большинство популярных языков программирования, а также во многие скриптовые языки, редакторы, приложения, базы данных, и утилиты командной строки.

    Регулярные выражения (RegEX) являются мощным, кратким и гибким инструментом для сопоставления строки текста, вроде отдельных символов, слов или шаблонов символов.

    Передав регулярное выражение в качестве значения атрибута pattern можно указать, какие значения приемлемы для данного поля ввода, а также проинформировав пользователя об ошибках.

    Давайте посмотрим на пару примеров использования регулярных выражений для валидации значения полей ввода.

    Телефонные номера

    Как упоминалось ранее, тип поля tel не полностью поддерживается браузерами из-за несоответствия форматов номеров телефонов в разных странах.

    Например, в некоторых странах формат телефонных номеров представляется в виде xxxx-xxx-xxxx , и сам телефонный номер будет что-то вроде этого: 0803-555-8205 .

    Регулярное выражение, которому соответствует данный шаблон, такое: ^\d{4}-\d{3}-\d{4}$ . В коде это можно записатьтак :

    Phone Number:

    Буквенно-цифровые значения Атрибут required

    Это атрибут булевого типа, использующийся для указания того, что значение данного поле обязательно заполнить для того, чтобы отправить форму. При добавлении этого атрибута полю браузер потребует от пользователя заполнить данное поле перед отправкой формы.

    Это избавляет нас от реализации проверки полей с помощью JavaScript, что может сохранить немного времени разработчикам.

    Например: или (для совместимости с XHTML)

    Во всех демках, которые вы видели выше, используют атрибут required , так что вы можете попробовать его в действии, попытавшись отослать форму без заполнения полей.

    Заключение

    Поддержка валидации форм браузерами довольно хороша , а для старых браузеров вы можете использовать полифиллы.

    Стоит отметить, что надеяться на валидацию только на стороне браузера опасно, так как эти проверки могут быть легко обойдены злоумышленниками или ботами.

    Не все браузеры поддерживают HTML5, и не все данные, посланные вашему скрипту, придут с вашей формы. Это значит, что перед тем, как окончательно принять данные от пользователя, необходимо проверить их корректность на стороне сервера.

    This and the next chapters show how to use PHP to validate form data.

    PHP Form Validation

    Think SECURITY when processing PHP forms!

    These pages will show how to process PHP forms with security in mind. Proper validation of form data is important to protect your form from hackers and spammers!

    The HTML form we will be working at in these chapters, contains various input fields: required and optional text fields, radio buttons, and a submit button:

    The validation rules for the form above are as follows:

    Field Validation Rules
    Name Required. + Must only contain letters and whitespace
    E-mail Required. + Must contain a valid email address (with @ and .)
    Website Optional. If present, it must contain a valid URL
    Comment Optional. Multi-line input field (textarea)
    Gender Required. Must select one

    First we will look at the plain HTML code for the form:

    Text Fields

    The name, email, and website fields are text input elements, and the comment field is a textarea. The HTML code looks like this:

    Name:
    E-mail:
    Website:
    Comment:

    Radio Buttons

    The gender fields are radio buttons and the HTML code looks like this:

    Gender:
    Female
    Male
    Other

    The Form Element

    The HTML code of the form looks like this: