{"id":2497,"date":"2021-09-03T12:23:40","date_gmt":"2021-09-03T12:23:40","guid":{"rendered":"https:\/\/phptutorial.net\/?page_id=2497"},"modified":"2024-08-18T02:06:58","modified_gmt":"2024-08-18T02:06:58","slug":"php-validation","status":"publish","type":"page","link":"https:\/\/www.phptutorial.net\/php-tutorial\/php-validation\/","title":{"rendered":"PHP Validation"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn to build a reusable PHP validation library from scratch.<\/p>\n\n\n\n<p>In previous tutorials, you learned how to validate a form field using the <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-filter_input\/\">filter_input()<\/a><\/code> and <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-filter_var\/\">filter_var()<\/a><\/code> functions. For example, the following sanitizes and validates the <code>email<\/code> field in the <code>POST<\/code> request:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ validate email<\/span>\n$email = filter_input(INPUT_POST, <span class=\"hljs-string\">'email'<\/span>, FILTER_SANITIZE_EMAIL);\n$inputs&#91;<span class=\"hljs-string\">'email'<\/span>] = $email;\n<span class=\"hljs-keyword\">if<\/span> ($email) {\n    $email = filter_var($email, FILTER_SANITIZE_EMAIL);\n    <span class=\"hljs-keyword\">if<\/span> (!$email) {\n        $errors&#91;<span class=\"hljs-string\">'email'<\/span>] = <span class=\"hljs-string\">'Please enter a valid email'<\/span>;\n    }\n} <span class=\"hljs-keyword\">else<\/span> {\n    $errors&#91;<span class=\"hljs-string\">'email'<\/span>] = <span class=\"hljs-string\">'Please enter an email'<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This code works fine. However, it&#8217;s pretty lengthy and not reusable. So let&#8217;s build a reusable validation library.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='define-validation-rules'>Define validation rules <a href=\"#define-validation-rules\" class=\"anchor\" id=\"define-validation-rules\" title=\"Anchor for Define validation rules\">#<\/a><\/h2>\n\n\n\n<p>Each field has one or more validation rules. For example, the <code>email<\/code> field is required and must be a valid email address, so the email field has two rules:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>required<\/li>\n\n\n\n<li>email<\/li>\n<\/ul>\n\n\n\n<p>The <code>username<\/code> is required and between 3 and 255 characters. Also, it should contain only letters and numbers. Therefore, the <code>username<\/code> field has three rules:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>required<\/li>\n\n\n\n<li>between 3 and 20 characters<\/li>\n\n\n\n<li>alphanumeric<\/li>\n<\/ul>\n\n\n\n<p>To define rules for fields, you can define a <code>$fields<\/code> array like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$fields = &#91;\n    <span class=\"hljs-string\">'email'<\/span>=&gt; <span class=\"hljs-string\">'required | email'<\/span>,\n    <span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'required | alphanumeric | between: 3,255\n];<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Each element in the <code>$fields<\/code> array has the <code>key<\/code> as the field name and value as the rules. We use the | character to separate two rules.<\/p>\n\n\n\n<p>If a rule has parameters, e.g., <code>between: 3, 25<\/code>, we use the <code>:<\/code> character to separate the rule name and its parameters. Also, we use the comma <code>,<\/code> to separate two parameters.<\/p>\n\n\n\n<p>We&#8217;ll create the following rules:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Rule<\/th><th>Rule name<\/th><th>Parameter<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td>required<\/td><td>required<\/td><td>No<\/td><td>The field is set and not empty<\/td><\/tr><tr><td>alphanumeric<\/td><td> alphanumeric <\/td><td>No<\/td><td>The field only contains letters and numbers<\/td><\/tr><tr><td>email<\/td><td>email<\/td><td>No<\/td><td>The field is a valid email address<\/td><\/tr><tr><td>secure<\/td><td>secure<\/td><td>No<\/td><td>The field must have between 8 and 64 characters and contain at least one number, one uppercase letter, one lowercase letter, and one special character. This rule is for the password field.<\/td><\/tr><tr><td>min: 3<\/td><td>min<\/td><td>An integer specifies the minimum length of the field<\/td><td>The length of the field must be greater than or equal to the length, e.g., 3<\/td><\/tr><tr><td>max: 255<\/td><td>max<\/td><td>An integer specifies the maximum length of the field <\/td><td>The length of the field must be less than or equal to the length, e.g., 255<\/td><\/tr><tr><td>same: another_field<\/td><td>same<\/td><td>The name of another field<\/td><td>The field value must be the same as the value of the another_field<\/td><\/tr><tr><td>between: min, max<\/td><td>between<\/td><td>min and max are integers that specify the minimum and maximum length of the field<\/td><td>The length of the field must be between min and max.<\/td><\/tr><tr><td>unique: table, column<\/td><td>unique<\/td><td>column and table in a relational database. Or field and collection in a NoSQL database<\/td><td>The field value must be unique in the column of the table in a database<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The following example defines the fields with rules:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$fields = &#91;\n    <span class=\"hljs-string\">'firstname'<\/span> =&gt; <span class=\"hljs-string\">'required, max:255'<\/span>,\n    <span class=\"hljs-string\">'lastname'<\/span> =&gt; <span class=\"hljs-string\">'required, max: 255'<\/span>,\n    <span class=\"hljs-string\">'address'<\/span> =&gt; <span class=\"hljs-string\">'required | min: 10, max:255'<\/span>,\n    <span class=\"hljs-string\">'zipcode'<\/span> =&gt; <span class=\"hljs-string\">'between: 5,6'<\/span>,\n    <span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'required | alphanumeric | between: 3,255 | unique: users,username'<\/span>,\n    <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'required | email | unique: users,email'<\/span>,\n    <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'required | secure'<\/span>,\n    <span class=\"hljs-string\">'password2'<\/span> =&gt; <span class=\"hljs-string\">'required | same:password'<\/span>\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='the-validate-function'>The validate() function <a href=\"#the-validate-function\" class=\"anchor\" id=\"the-validate-function\" title=\"Anchor for The validate() function\">#<\/a><\/h2>\n\n\n\n<p>The validation library should have the <code>validate()<\/code> function that accepts an associative array of data to validate <code>$data<\/code> and the <code>$fields<\/code> array that contains the validation rules:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It should return an array that contains the validation errors, in which the key of each element is the field name and the value is the error message:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    <span class=\"hljs-comment\">\/\/ implementation<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>validate()<\/code> function will need to iterate over the <code>$fields<\/code>. It loops through rules for each field and validates the value against each rule. If the validation fails, it&#8217;ll add an error message to an <code>$errors<\/code> array:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span> : <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    $errors = &#91;];\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n        <span class=\"hljs-comment\">\/\/ get the rules of the field<\/span>\n        $rules = split($option);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            <span class=\"hljs-comment\">\/\/ run a validation rule for each field<\/span>\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Since the rules of a field is a string, you need to separate the rules using the <code>|<\/code> character. Also, you need to strip all the whitespaces. To do that, you can define an arrow function to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, split a string by a separator.<\/li>\n\n\n\n<li>Then, trim each item in the result array and return it.<\/li>\n<\/ul>\n\n\n\n<p>The arrow function will look like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The arrow function accepts a string and a separator. The <code>explode()<\/code> function splits the <code>$str<\/code> by the <code>$separator<\/code>. The result of the <code>explode()<\/code> function is an array of strings.<\/p>\n\n\n\n<p>The <code>array_map()<\/code> function executes the <code>trim()<\/code> function on each item and returns a new array of items with the whitespaces removed.<\/p>\n\n\n\n<p>The validate() function is updated to include the arrow function as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span>\n<\/span>{\n\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    $errors = &#91;];\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n        <span class=\"hljs-comment\">\/\/ get the rules of the field<\/span>\n        $rules =  $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            <span class=\"hljs-comment\">\/\/ run a validation on each rule<\/span>\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>$rule<\/code> may or may not have parameters. If it has parameters, it&#8217;ll contain the <code>:<\/code> character. The following code extracts the rule name and its parameters:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n    &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n    $params = $split($$param_str, <span class=\"hljs-string\">','<\/span>);\n} <span class=\"hljs-keyword\">else<\/span> {\n    $rule_name = trim($rule);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You use the <code>$split<\/code> arrow function in this code to split the rule by the <code>:<\/code> character. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">between: <span class=\"hljs-number\">3<\/span>,<span class=\"hljs-number\">255<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>will become two strings:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-string\">'between'<\/span>\n<span class=\"hljs-string\">'3,255'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following uses the array destructuring to assign the first and second elements of the result of the <code>$split<\/code> function to the <code>$rule_name<\/code> and<code>$param_str<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>For example, the rule <code>\"between : 3, 255\"<\/code> will result in:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$rule_name = <span class=\"hljs-string\">'between'<\/span>;\n$param_str = <span class=\"hljs-string\">'3, 255'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To get the parameter list, you pass the <code>$param_str<\/code> to the <code>$split()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$params = $split($param_str, <span class=\"hljs-string\">','<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>validate()<\/code> function will look like the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    $errors = &#91;];\n\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            $params = &#91;];\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, you have fields and their rule names with parameters.<\/p>\n\n\n\n<p>To execute validation for each rule, you can have a big <code>if-elseif<\/code> statement like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span>($rule_name === <span class=\"hljs-string\">'required'<\/span>) {\n\n} <span class=\"hljs-keyword\">elseif<\/span>($rule_name === <span class=\"hljs-string\">'email'<\/span>) {\n\n} ...<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>However, this approach has two issues:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, a big if-elseif is hard to maintain.<\/li>\n\n\n\n<li>Second, if you want to add a new rule, you must change the <code>validate()<\/code> function, which is not ideal.<\/li>\n<\/ul>\n\n\n\n<p>You want the validate() function to be more dynamic so that we don&#8217;t need to change the function when you add a new rule later. To do that, you can use the <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-variable-functions\/\">variable functions<\/a>.<\/p>\n\n\n\n<p>For each rule, you call the validation function dynamically like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$rule_name($data, $field, ...$params);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first and second arguments of the validation function are <code>$data<\/code> and <code>$field<\/code>. The third argument is a list of arguments spread from the array <code>$params<\/code>.<\/p>\n\n\n\n<p>For example, if the <code>$params<\/code> is <code>[3,255]<\/code>, the <code>...$params<\/code> will return 3 and 255.<\/p>\n\n\n\n<p>So the rule <code>'between: 3, 255'<\/code> of the <code>username<\/code> with the value <code>\"john\"<\/code> will result in the following function call:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">between($data, <span class=\"hljs-string\">'username'<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">255<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To prevent the validation function from collie with the standard function like <code>min<\/code>, you can prefix our validation function with the string <code>is_<\/code>. For example, the <code>between<\/code> rule will execute the <code>is_between<\/code> validation function.<\/p>\n\n\n\n<p>The following shows the updated <code>validate()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    $errors = &#91;];\n\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            $params = &#91;];\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n\n            $fn = <span class=\"hljs-string\">'is_'<\/span> . $rule_name;\n\n            <span class=\"hljs-keyword\">if<\/span> (is_callable($fn)) {\n                $pass = $fn($data, $field, ...$params);\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this <code>validate()<\/code> function, you use the <code>is_callable()<\/code> function to check if the <code>is_rule_name<\/code> is a callable before calling it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='returning-error-messages'>Returning error messages <a href=\"#returning-error-messages\" class=\"anchor\" id=\"returning-error-messages\" title=\"Anchor for Returning error messages\">#<\/a><\/h3>\n\n\n\n<p>Each rule should have a specific error message. If validation fails, you need to store the error message in the <code>$error<\/code> array. Also, you should be able to return an error message with the parameters.<\/p>\n\n\n\n<p>For example, if the following rule fails:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'between: 3, 255'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You should return the error message:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">The username should be between <span class=\"hljs-number\">3<\/span> <span class=\"hljs-keyword\">and<\/span> <span class=\"hljs-number\">255<\/span> characters.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To do that, first, you define the default validation error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> DEFAULT_VALIDATION_ERRORS = &#91;\n    <span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'Please enter the %s'<\/span>,\n    <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'The %s is not a valid email address'<\/span>,\n    <span class=\"hljs-string\">'min'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have at least %s characters'<\/span>,\n    <span class=\"hljs-string\">'max'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have at most %s characters'<\/span>,\n    <span class=\"hljs-string\">'between'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have between %d and %d characters'<\/span>,\n    <span class=\"hljs-string\">'same'<\/span> =&gt; <span class=\"hljs-string\">'The %s must match with %s'<\/span>,\n    <span class=\"hljs-string\">'alphanumeric'<\/span> =&gt; <span class=\"hljs-string\">'The %s should have only letters and numbers'<\/span>,\n    <span class=\"hljs-string\">'secure'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have between 8 and 64 characters and contain at least one number, one upper case letter, one lower case letter and one special character'<\/span>,\n    <span class=\"hljs-string\">'unique'<\/span> =&gt; <span class=\"hljs-string\">'The %s already exists'<\/span>,\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>DEFAULT_VALIDATION_ERRORS<\/code> array, the key is the rule name, while the value is the error message. The error message has <code>%s<\/code> or <code>%d<\/code> placeholders so that you can use the <code>sprintf()<\/code> function to format the error message with parameters like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">sprintf(DEFAULT_VALIDATION_ERRORS&#91;$rule_name], $field, ...$params);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here&#8217;s the <code>validate()<\/code> function with error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields)<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    $errors = &#91;];\n\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            $params = &#91;];\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n\n            $fn = <span class=\"hljs-string\">'is_'<\/span> . $rule_name;\n\n            <span class=\"hljs-keyword\">if<\/span> (is_callable($fn)) {\n                $pass = $fn($data, $field , ...$params);\n                <span class=\"hljs-keyword\">if<\/span> (!$pass) {\n                    $errors&#91;$field] = sprintf(DEFAULT_VALIDATION_ERRORS&#91;$rule_name], $field, ...$params);\n                }\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='adding-custom-error-messages'>Adding custom error messages <a href=\"#adding-custom-error-messages\" class=\"anchor\" id=\"adding-custom-error-messages\" title=\"Anchor for Adding custom error messages\">#<\/a><\/h3>\n\n\n\n<p>The <code>validate()<\/code> function uses the default error messages. However, sometimes, you need to pass our custom error message. <\/p>\n\n\n\n<p>For example, you may want to use a message like <code>'The username is required'<\/code> for the <code>required<\/code> rule instead of using the default one.<\/p>\n\n\n\n<p>To do that, you can add a third parameter to the <code>validate()<\/code> function to store the custom error messages. This parameter is an array of items whose key is the field name and whose value is the error message. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&#91;<span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'The %s is required'<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you pass the custom error messages array to the <code>validate()<\/code> function, it will be used instead of the default one.<\/p>\n\n\n\n<p>Here&#8217;s the <code>validate()<\/code> function with the custom error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields, array $messages = &#91;])<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-comment\">\/\/ set the validation messages<\/span>\n    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);\n\n    $errors = &#91;];\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n\n            $params = &#91;];\n\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n\n            $fn = <span class=\"hljs-string\">'is_'<\/span> . $rule_name;\n\n            <span class=\"hljs-keyword\">if<\/span> (is_callable($fn)) {\n                $pass = $fn($data, $field, ...$params);\n                <span class=\"hljs-keyword\">if<\/span> (!$pass) {\n                    $errors&#91;$field] = sprintf($validation_errors&#91;$rule_name], $field, ...$params);\n                }\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>validate()<\/code> function:<\/p>\n\n\n\n<p>First, merge the default error messages with the custom error messages. The custom error message will overwrite the default error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, get the error messages from the <code>$validation_errors<\/code> instead of the <code>DEFAULT_VALIDATION_ERRORS<\/code> array:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$errors&#91;$field] = sprintf($validation_errors&#91;$rule_name], $field, ...$params);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='add-a-custom-error-message-for-each-field-and-rule'>Add a custom error message for each field and rule <a href=\"#add-a-custom-error-message-for-each-field-and-rule\" class=\"anchor\" id=\"add-a-custom-error-message-for-each-field-and-rule\" title=\"Anchor for Add a custom error message for each field and rule\">#<\/a><\/h3>\n\n\n\n<p>So far, a custom error message is applied to a specific rule of all fields. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-attr\">&#91;<span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'The % is required'<\/span>]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And you have two fields:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&#91;\n   <span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'required'<\/span>,\n   <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'required'<\/span>\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The custom error message will apply to both <code>username<\/code> and <code>password<\/code> fields.<\/p>\n\n\n\n<p>Sometimes, you want to apply a custom error message for a specific field. For example, you want the required rule of the username to have a message like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">Please <span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">your<\/span> <span class=\"hljs-title\">username<\/span> <span class=\"hljs-title\">to<\/span> <span class=\"hljs-title\">sign<\/span> <span class=\"hljs-title\">in<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And the custom error message for the password field is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">Use<\/span> <span class=\"hljs-title\">your<\/span> <span class=\"hljs-title\">password<\/span> <span class=\"hljs-title\">to<\/span> <span class=\"hljs-title\">sign<\/span> <span class=\"hljs-title\">in<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To do that, you need to enhance the <code>validate()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields, array $messages = &#91;])<\/span>: <span class=\"hljs-title\">array<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>$messages<\/code> variable will look like the following to support a custom message for a specific rule and field:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&#91;\n    <span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'The %s is required'<\/span>,\n    <span class=\"hljs-string\">'username'<\/span> =&gt; &#91;<span class=\"hljs-string\">'required'<\/span>=&gt; <span class=\"hljs-string\">'Please use your username to sign in'<\/span>]\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first element will set the error message for the required rule of all fields:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'The %s is required'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The second element will set the error message for the required rule of the username:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-string\">'username'<\/span> =&gt; &#91;<span class=\"hljs-string\">'required'<\/span>=&gt; <span class=\"hljs-string\">'Please use your username to sign in'<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the element&#8217;s value is a string, it is the error message for a rule of all fields. The key is the rule name, and the value is an error message.<\/p>\n\n\n\n<p>However, if the element&#8217;s value is an array, the key is the field name, and the value is an array of rules and error messages.<\/p>\n\n\n\n<p>The following returns an array that contains a list of rules and error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$rule_messages = array_filter($messages, fn($message) =&gt;  is_string($message));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Once having this <code>$rule_messages<\/code> array, you can merge it with the default error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following gets the error message for a field and rule if it exists:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$message&#91;$field]&#91;$rule] <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Otherwise, you can get the error message from the <code>$validation_errors<\/code> above:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$validation_errors&#91;$rule_name]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following shows the <code>validate()<\/code> function with the new logic for custom error messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/**\n * Validate\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> array $fields\n * <span class=\"hljs-doctag\">@param<\/span> array $messages\n * <span class=\"hljs-doctag\">@return<\/span> array\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields, array $messages = &#91;])<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    <span class=\"hljs-comment\">\/\/ Split the array by a separator, trim each element<\/span>\n    <span class=\"hljs-comment\">\/\/ and return the array<\/span>\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-comment\">\/\/ get the message rules<\/span>\n    $rule_messages = array_filter($messages, fn($message) =&gt;  is_string($message));\n    \n    <span class=\"hljs-comment\">\/\/ overwrite the default message<\/span>\n    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);\n\n    $errors = &#91;];\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            <span class=\"hljs-comment\">\/\/ get rule name params<\/span>\n            $params = &#91;];\n            <span class=\"hljs-comment\">\/\/ if the rule has parameters e.g., min: 1<\/span>\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n            <span class=\"hljs-comment\">\/\/ by convention, the callback should be is_&lt;rule&gt; e.g.,is_required<\/span>\n            $fn = <span class=\"hljs-string\">'is_'<\/span> . $rule_name;\n\n            <span class=\"hljs-keyword\">if<\/span> (is_callable($fn)) {\n                $pass = $fn($data, $field, ...$params);\n                <span class=\"hljs-keyword\">if<\/span> (!$pass) {\n                    <span class=\"hljs-comment\">\/\/ get the error message for a specific field and rule if exists<\/span>\n                    <span class=\"hljs-comment\">\/\/ otherwise get the error message from the $validation_errors<\/span>\n                    $errors&#91;$field] = sprintf(\n                        $messages&#91;$field]&#91;$rule_name] ?? $validation_errors&#91;$rule_name],\n                        $field,\n                        ...$params\n                    );\n                }\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-41\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So far, you have completed the <code>validate()<\/code> function. Let&#8217;s define the validation function for each rule.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='validation-functions'>Validation functions <a href=\"#validation-functions\" class=\"anchor\" id=\"validation-functions\" title=\"Anchor for Validation functions\">#<\/a><\/h2>\n\n\n\n<p>Each validation function must have the following signature:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validation_function<\/span><span class=\"hljs-params\">(array $data, string $field, ....$params)<\/span> : <span class=\"hljs-title\">bool<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-42\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='required-rule'>required rule <a href=\"#required-rule\" class=\"anchor\" id=\"required-rule\" title=\"Anchor for required rule\">#<\/a><\/h3>\n\n\n\n<p>The following <code>is_required()<\/code> function returns true if the value is set and not empty:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_required<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">isset<\/span>($data&#91;$field]) &amp;&amp; trim($data&#91;$field]) !== <span class=\"hljs-string\">''<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='email-rule'>email rule <a href=\"#email-rule\" class=\"anchor\" id=\"email-rule\" title=\"Anchor for email rule\">#<\/a><\/h3>\n\n\n\n<p>The following <code>is_email()<\/code> function returns true if the value is a valid email address:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_email<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">empty<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> filter_var($data&#91;$field], FILTER_VALIDATE_EMAIL);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If <code>$data[$field]<\/code> is not set or empty, the <code>is_email()<\/code> function also returns <code>true<\/code> .<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='min-rule'>min rule <a href=\"#min-rule\" class=\"anchor\" id=\"min-rule\" title=\"Anchor for min rule\">#<\/a><\/h3>\n\n\n\n<p>The following <code>is_min()<\/code> function returns true if the field value&#8217;s length is greater than or equal to $min:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-45\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_min<\/span><span class=\"hljs-params\">(array $data, string $field, int $min)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> mb_strlen($data&#91;$field]) &gt;= $min;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-45\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='max-rule'>max rule <a href=\"#max-rule\" class=\"anchor\" id=\"max-rule\" title=\"Anchor for max rule\">#<\/a><\/h3>\n\n\n\n<p>The following <code>is_max()<\/code> function returns true if the field value length is less than or equal to $max:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-46\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_max<\/span><span class=\"hljs-params\">(array $data, string $field, int $max)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> mb_strlen($data&#91;$field]) &lt;= $max;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-46\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='between-rule'>between rule <a href=\"#between-rule\" class=\"anchor\" id=\"between-rule\" title=\"Anchor for between rule\">#<\/a><\/h3>\n\n\n\n<p>The following <code>is_between()<\/code> function returns <code>true<\/code> if the field value&#8217;s length is between <code>$min<\/code> and <code>$max<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-47\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_between<\/span><span class=\"hljs-params\">(array $data, string $field, int $min, int $max)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    $len = mb_strlen($data&#91;$field]);\n    <span class=\"hljs-keyword\">return<\/span> $len &gt;= $min &amp;&amp; $len &lt;= $max;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-47\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='alphanumeric-rule'>alphanumeric rule <a href=\"#alphanumeric-rule\" class=\"anchor\" id=\"alphanumeric-rule\" title=\"Anchor for alphanumeric rule\">#<\/a><\/h3>\n\n\n\n<p>The <code>is_alphanumeric()<\/code> returns true if the field value contains only letters or characters:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-48\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_alphanumeric<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> ctype_alnum($data&#91;$field]);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-48\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='same-rule'>same rule <a href=\"#same-rule\" class=\"anchor\" id=\"same-rule\" title=\"Anchor for same rule\">#<\/a><\/h3>\n\n\n\n<p>The <code>is_same()<\/code> function returns <code>true<\/code> if the field value is the same as the other field&#8217;s value:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-49\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_same<\/span><span class=\"hljs-params\">(array $data, string $field, string $other)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field], $data&#91;$other])) {\n        <span class=\"hljs-keyword\">return<\/span> $data&#91;$field] === $data&#91;$other];\n    }\n\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field]) &amp;&amp; !<span class=\"hljs-keyword\">isset<\/span>($data&#91;$other])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-49\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='secure-rule'>secure rule <a href=\"#secure-rule\" class=\"anchor\" id=\"secure-rule\" title=\"Anchor for secure rule\">#<\/a><\/h3>\n\n\n\n<p>The <code>is_secure()<\/code> returns true if the field value must have between 8 and 64 characters and contain at least one number, one upper case letter, one lower case letter, and one special character:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-50\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_secure<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n    }\n\n    $pattern = <span class=\"hljs-string\">\"#.*^(?=.{8,64})(?=.*&#91;a-z])(?=.*&#91;A-Z])(?=.*&#91;0-9])(?=.*\\W).*$#\"<\/span>;\n    <span class=\"hljs-keyword\">return<\/span> preg_match($pattern, $data&#91;$field]);\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-50\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='unique-rule'>unique rule <a href=\"#unique-rule\" class=\"anchor\" id=\"unique-rule\" title=\"Anchor for unique rule\">#<\/a><\/h3>\n\n\n\n<p>For the <code>unique<\/code> rule, you need a database connection and select the value from the <code>$column<\/code> of a <code>$table<\/code> specified in the rule&#8217;s parameters.<\/p>\n\n\n\n<p>First, create a new file called <code>database.php<\/code> in the <code>config<\/code> folder and add the following constants:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-51\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> DB_HOST = <span class=\"hljs-string\">'localhost'<\/span>;\n<span class=\"hljs-keyword\">const<\/span> DB_NAME = <span class=\"hljs-string\">'auth'<\/span>;\n<span class=\"hljs-keyword\">const<\/span> DB_USER = <span class=\"hljs-string\">'root'<\/span>;\n<span class=\"hljs-keyword\">const<\/span> DB_PASSWORD = <span class=\"hljs-string\">''<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-51\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, load the <code>config\/database.php<\/code> and define a function to <a href=\"https:\/\/phptutorial.net\/php-pdo\/pdo-connecting-to-mysql\/\">connect to the database<\/a>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-52\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">db<\/span><span class=\"hljs-params\">()<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">static<\/span> $pdo;\n    <span class=\"hljs-keyword\">if<\/span> (!$pdo) {\n        $pdo = connect(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);\n    }\n    <span class=\"hljs-keyword\">return<\/span> $pdo;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-52\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following <code>is_unique()<\/code> function returns true if the value is unique is the <code>$column<\/code> of the <code>$table<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-53\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_unique<\/span><span class=\"hljs-params\">(array $data, string $field, string $table, string $column)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    $sql = <span class=\"hljs-string\">\"SELECT $column FROM $table WHERE $column = :value\"<\/span>;\n\n    $stmt = db()-&gt;prepare($sql);\n    $stmt-&gt;bindValue(<span class=\"hljs-string\">\":value\"<\/span>, $data&#91;$field]);\n\n    $stmt-&gt;execute();\n\n    <span class=\"hljs-keyword\">return<\/span> $stmt-&gt;fetchColumn() === <span class=\"hljs-keyword\">false<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-53\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='putting-it-all-together'>Putting it all together <a href=\"#putting-it-all-together\" class=\"anchor\" id=\"putting-it-all-together\" title=\"Anchor for Putting it all together\">#<\/a><\/h2>\n\n\n\n<p>The following shows all functions in the validation library:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-54\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/..\/config\/database.php'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> DEFAULT_VALIDATION_ERRORS = &#91;\n    <span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'Please enter the %s'<\/span>,\n    <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'The %s is not a valid email address'<\/span>,\n    <span class=\"hljs-string\">'min'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have at least %s characters'<\/span>,\n    <span class=\"hljs-string\">'max'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have at most %s characters'<\/span>,\n    <span class=\"hljs-string\">'between'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have between %d and %d characters'<\/span>,\n    <span class=\"hljs-string\">'same'<\/span> =&gt; <span class=\"hljs-string\">'The %s must match with %s'<\/span>,\n    <span class=\"hljs-string\">'alphanumeric'<\/span> =&gt; <span class=\"hljs-string\">'The %s should have only letters and numbers'<\/span>,\n    <span class=\"hljs-string\">'secure'<\/span> =&gt; <span class=\"hljs-string\">'The %s must have between 8 and 64 characters and contain at least one number, one upper case letter, one lower case letter and one special character'<\/span>,\n    <span class=\"hljs-string\">'unique'<\/span> =&gt; <span class=\"hljs-string\">'The %s already exists'<\/span>,\n];\n\n\n<span class=\"hljs-comment\">\/**\n * Validate\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> array $fields\n * <span class=\"hljs-doctag\">@param<\/span> array $messages\n * <span class=\"hljs-doctag\">@return<\/span> array\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">validate<\/span><span class=\"hljs-params\">(array $data, array $fields, array $messages = &#91;])<\/span>: <span class=\"hljs-title\">array<\/span>\n<\/span>{\n    <span class=\"hljs-comment\">\/\/ Split the array by a separator, trim each element<\/span>\n    <span class=\"hljs-comment\">\/\/ and return the array<\/span>\n    $split = fn($str, $separator) =&gt; array_map(<span class=\"hljs-string\">'trim'<\/span>, explode($separator, $str));\n\n    <span class=\"hljs-comment\">\/\/ get the message rules<\/span>\n    $rule_messages = array_filter($messages, fn($message) =&gt; is_string($message));\n    <span class=\"hljs-comment\">\/\/ overwrite the default message<\/span>\n    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);\n\n    $errors = &#91;];\n\n    <span class=\"hljs-keyword\">foreach<\/span> ($fields <span class=\"hljs-keyword\">as<\/span> $field =&gt; $option) {\n\n        $rules = $split($option, <span class=\"hljs-string\">'|'<\/span>);\n\n        <span class=\"hljs-keyword\">foreach<\/span> ($rules <span class=\"hljs-keyword\">as<\/span> $rule) {\n            <span class=\"hljs-comment\">\/\/ get rule name params<\/span>\n            $params = &#91;];\n            <span class=\"hljs-comment\">\/\/ if the rule has parameters e.g., min: 1<\/span>\n            <span class=\"hljs-keyword\">if<\/span> (strpos($rule, <span class=\"hljs-string\">':'<\/span>)) {\n                &#91;$rule_name, $param_str] = $split($rule, <span class=\"hljs-string\">':'<\/span>);\n                $params = $split($param_str, <span class=\"hljs-string\">','<\/span>);\n            } <span class=\"hljs-keyword\">else<\/span> {\n                $rule_name = trim($rule);\n            }\n            <span class=\"hljs-comment\">\/\/ by convention, the callback should be is_&lt;rule&gt; e.g.,is_required<\/span>\n            $fn = <span class=\"hljs-string\">'is_'<\/span> . $rule_name;\n\n            <span class=\"hljs-keyword\">if<\/span> (is_callable($fn)) {\n                $pass = $fn($data, $field, ...$params);\n                <span class=\"hljs-keyword\">if<\/span> (!$pass) {\n                    <span class=\"hljs-comment\">\/\/ get the error message for a specific field and rule if exists<\/span>\n                    <span class=\"hljs-comment\">\/\/ otherwise get the error message from the $validation_errors<\/span>\n                    $errors&#91;$field] = sprintf(\n                        $messages&#91;$field]&#91;$rule_name] ?? $validation_errors&#91;$rule_name],\n                        $field,\n                        ...$params\n                    );\n                }\n            }\n        }\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> $errors;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a string is not empty\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_required<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">isset<\/span>($data&#91;$field]) &amp;&amp; trim($data&#91;$field]) !== <span class=\"hljs-string\">''<\/span>;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if the value is a valid email\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_email<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">empty<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> filter_var($data&#91;$field], FILTER_VALIDATE_EMAIL);\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a string has at least min length\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@param<\/span> int $min\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_min<\/span><span class=\"hljs-params\">(array $data, string $field, int $min)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> mb_strlen($data&#91;$field]) &gt;= $min;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a string cannot exceed max length\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@param<\/span> int $max\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_max<\/span><span class=\"hljs-params\">(array $data, string $field, int $max)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> mb_strlen($data&#91;$field]) &lt;= $max;\n}\n\n<span class=\"hljs-comment\">\/**\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@param<\/span> int $min\n * <span class=\"hljs-doctag\">@param<\/span> int $max\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_between<\/span><span class=\"hljs-params\">(array $data, string $field, int $min, int $max)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    $len = mb_strlen($data&#91;$field]);\n    <span class=\"hljs-keyword\">return<\/span> $len &gt;= $min &amp;&amp; $len &lt;= $max;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a string equals the other\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@param<\/span> string $other\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_same<\/span><span class=\"hljs-params\">(array $data, string $field, string $other)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field], $data&#91;$other])) {\n        <span class=\"hljs-keyword\">return<\/span> $data&#91;$field] === $data&#91;$other];\n    }\n\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field]) &amp;&amp; !<span class=\"hljs-keyword\">isset<\/span>($data&#91;$other])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a string is alphanumeric\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_alphanumeric<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    <span class=\"hljs-keyword\">return<\/span> ctype_alnum($data&#91;$field]);\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if a password is secure\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_secure<\/span><span class=\"hljs-params\">(array $data, string $field)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n    }\n\n    $pattern = <span class=\"hljs-string\">\"#.*^(?=.{8,64})(?=.*&#91;a-z])(?=.*&#91;A-Z])(?=.*&#91;0-9])(?=.*\\W).*$#\"<\/span>;\n    <span class=\"hljs-keyword\">return<\/span> preg_match($pattern, $data&#91;$field]);\n}\n\n\n<span class=\"hljs-comment\">\/**\n * Connect to the database and returns an instance of PDO class\n * or false if the connection fails\n *\n * <span class=\"hljs-doctag\">@return<\/span> PDO\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">db<\/span><span class=\"hljs-params\">()<\/span>: <span class=\"hljs-title\">PDO<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">static<\/span> $pdo;\n    <span class=\"hljs-comment\">\/\/ if the connection is not initialized<\/span>\n    <span class=\"hljs-comment\">\/\/ connect to the database<\/span>\n    <span class=\"hljs-keyword\">if<\/span> (!$pdo) {\n        $pdo = <span class=\"hljs-keyword\">new<\/span> PDO(\n            sprintf(<span class=\"hljs-string\">\"mysql:host=%s;dbname=%s;charset=UTF8\"<\/span>, DB_HOST, DB_NAME),\n            DB_USER,\n            DB_PASSWORD,\n            &#91;PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION]\n        );\n    }\n    <span class=\"hljs-keyword\">return<\/span> $pdo;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return true if the $value is unique in the column of a table\n * <span class=\"hljs-doctag\">@param<\/span> array $data\n * <span class=\"hljs-doctag\">@param<\/span> string $field\n * <span class=\"hljs-doctag\">@param<\/span> string $table\n * <span class=\"hljs-doctag\">@param<\/span> string $column\n * <span class=\"hljs-doctag\">@return<\/span> bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_unique<\/span><span class=\"hljs-params\">(array $data, string $field, string $table, string $column)<\/span>: <span class=\"hljs-title\">bool<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (!<span class=\"hljs-keyword\">isset<\/span>($data&#91;$field])) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    }\n\n    $sql = <span class=\"hljs-string\">\"SELECT $column FROM $table WHERE $column = :value\"<\/span>;\n\n    $stmt = db()-&gt;prepare($sql);\n    $stmt-&gt;bindValue(<span class=\"hljs-string\">\":value\"<\/span>, $data&#91;$field]);\n\n    $stmt-&gt;execute();\n\n    <span class=\"hljs-keyword\">return<\/span> $stmt-&gt;fetchColumn() === <span class=\"hljs-keyword\">false<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-54\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='testing-the-validation-library'>Testing the validation library <a href=\"#testing-the-validation-library\" class=\"anchor\" id=\"testing-the-validation-library\" title=\"Anchor for Testing the validation library\">#<\/a><\/h2>\n\n\n\n<p>To test the <code>unique<\/code> rule, you need to create a new database and a table with the <code>username<\/code> field, for example.<\/p>\n\n\n\n<p>First, create a new database called <code>auth<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-55\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\"><span class=\"hljs-keyword\">CREATE<\/span> <span class=\"hljs-keyword\">DATABASE<\/span> auth;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-55\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, create a new <code>users<\/code> table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-56\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\"><span class=\"hljs-keyword\">CREATE<\/span> <span class=\"hljs-keyword\">TABLE<\/span> <span class=\"hljs-keyword\">users<\/span>(\n    <span class=\"hljs-keyword\">id<\/span> <span class=\"hljs-built_in\">INT<\/span> AUTO_INCREMENT PRIMARY <span class=\"hljs-keyword\">KEY<\/span>,\n    username <span class=\"hljs-built_in\">VARCHAR<\/span>(<span class=\"hljs-number\">255<\/span>) <span class=\"hljs-keyword\">NOT<\/span> <span class=\"hljs-literal\">NULL<\/span> <span class=\"hljs-keyword\">UNIQUE<\/span>,\n    email <span class=\"hljs-built_in\">VARCHAR<\/span>(<span class=\"hljs-number\">300<\/span>) <span class=\"hljs-keyword\">NOT<\/span> <span class=\"hljs-literal\">NULL<\/span> <span class=\"hljs-keyword\">UNIQUE<\/span>\n);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-56\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note that for testing purposes, we don&#8217;t need to have the <code>password<\/code> field.<\/p>\n\n\n\n<p>Third, insert a row into the <code>users<\/code> table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-57\" data-shcb-language-name=\"SQL (Structured Query Language)\" data-shcb-language-slug=\"sql\"><span><code class=\"hljs language-sql\"><span class=\"hljs-keyword\">INSERT<\/span> <span class=\"hljs-keyword\">INTO<\/span> <span class=\"hljs-keyword\">users<\/span>(username, email)\n<span class=\"hljs-keyword\">VALUES<\/span>(<span class=\"hljs-string\">'bob'<\/span>, <span class=\"hljs-string\">'bob@phptutorial.net'<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-57\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">SQL (Structured Query Language)<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">sql<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following example uses the <code>validate()<\/code> function to run a test:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-58\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/validation.php'<\/span>;\n\n$data = &#91;\n    <span class=\"hljs-string\">'firstname'<\/span> =&gt; <span class=\"hljs-string\">''<\/span>,\n    <span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'bob'<\/span>,\n    <span class=\"hljs-string\">'address'<\/span> =&gt; <span class=\"hljs-string\">'This is my address'<\/span>,\n    <span class=\"hljs-string\">'zipcode'<\/span> =&gt; <span class=\"hljs-string\">'999'<\/span>,\n    <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'jo@'<\/span>,\n    <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'test123'<\/span>,\n    <span class=\"hljs-string\">'password2'<\/span> =&gt; <span class=\"hljs-string\">'test'<\/span>,\n];\n\n\n\n$fields = &#91;\n    <span class=\"hljs-string\">'firstname'<\/span> =&gt; <span class=\"hljs-string\">'required | max:255'<\/span>,\n    <span class=\"hljs-string\">'lastname'<\/span> =&gt; <span class=\"hljs-string\">'required | max: 255'<\/span>,\n    <span class=\"hljs-string\">'address'<\/span> =&gt; <span class=\"hljs-string\">'required | min: 10, max:255'<\/span>,\n    <span class=\"hljs-string\">'zipcode'<\/span> =&gt; <span class=\"hljs-string\">'between: 5,6'<\/span>,\n    <span class=\"hljs-string\">'username'<\/span> =&gt; <span class=\"hljs-string\">'required | alphanumeric | between: 3,255 | unique: users,username'<\/span>,\n    <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'required | email | unique: users,email'<\/span>,\n    <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'required | secure'<\/span>,\n    <span class=\"hljs-string\">'password2'<\/span> =&gt; <span class=\"hljs-string\">'required | same:password'<\/span>\n];\n\n\n$errors = validate($data, $fields, &#91;\n    <span class=\"hljs-string\">'required'<\/span> =&gt; <span class=\"hljs-string\">'The %s is required'<\/span>,\n    <span class=\"hljs-string\">'password2'<\/span> =&gt; &#91;<span class=\"hljs-string\">'same'<\/span>=&gt; <span class=\"hljs-string\">'Please enter the same password again'<\/span>]]\n);\n\nprint_r($errors);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-58\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-59\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">Array<\/span>\n(\n    &#91;firstname] =&gt; The firstname is required\n    &#91;lastname] =&gt; The lastname is required\n    &#91;zipcode] =&gt; The zipcode must have between <span class=\"hljs-number\">5<\/span> <span class=\"hljs-keyword\">and<\/span> <span class=\"hljs-number\">6<\/span> characters\n    &#91;username] =&gt; The username already exists\n    &#91;email] =&gt; The email is not a valid email address\n    &#91;password] =&gt; The password must have between <span class=\"hljs-number\">8<\/span> <span class=\"hljs-keyword\">and<\/span> <span class=\"hljs-number\">64<\/span> characters <span class=\"hljs-keyword\">and<\/span> contain at least one number, one upper <span class=\"hljs-keyword\">case<\/span> letter, one lower <span class=\"hljs-keyword\">case<\/span> letter <span class=\"hljs-keyword\">and<\/span> o\nne special character\n    &#91;password2] =&gt; Please enter the same password again\n)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-59\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='adding-a-new-validation-rule'>Adding a new validation rule <a href=\"#adding-a-new-validation-rule\" class=\"anchor\" id=\"adding-a-new-validation-rule\" title=\"Anchor for Adding a new validation rule\">#<\/a><\/h2>\n\n\n\n<p>To add a new rule, you need to do two things:<\/p>\n\n\n\n<p>First, add a default error message to the <code>DEFAULT_VALIDATION_ERRORS<\/code> array.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-60\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> DEFAULT_VALIDATION_ERRORS = &#91;\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-params\">new_rule<\/span> =&gt;<\/span> <span class=\"hljs-string\">\"Error message for the new rule\"<\/span>\n\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-60\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, define a validation function with the following signature:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-61\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">is_new_rule<\/span><span class=\"hljs-params\">(array $data, string $field, ....$params)<\/span> : <span class=\"hljs-title\">bool<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-61\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this tutorial, you have learned how to build a reusable validation library in PHP.<\/p>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Did you find this tutorial useful?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"2497\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-validation\/\"\n\t\t\t\tdata-post-title=\"PHP Validation\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"2497\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-validation\/\"\n\t\t\t\tdata-post-title=\"PHP Validation\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to build a PHP validation library from scratch.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":15,"menu_order":97,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2497","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2497","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/comments?post=2497"}],"version-history":[{"count":5,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2497\/revisions"}],"predecessor-version":[{"id":2921,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2497\/revisions\/2921"}],"up":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/15"}],"wp:attachment":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/media?parent=2497"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}