Comment

PHP প্রসেসিং ফর্ম (Processing Forms)

PHP বৈধতা (Validation)

Estimated reading: 14 minutes 9 views Contributors

সারাংশ: এই টিউটোরিয়ালে, আপনি স্ক্র্যাচ থেকে একটি পুনঃব্যবহারযোগ্য পিএইচপি বৈধতা লাইব্রেরি তৈরি করতে শিখবেন।

পূর্ববর্তী টিউটোরিয়ালে, আপনি শিখেছেন কিভাবে filter_input() এবং filter_var() ফাংশন ব্যবহার করে একটি ফর্ম ফিল্ড যাচাই করতে হয়। উদাহরণস্বরূপ, নিম্নলিখিতগুলি POST অনুরোধে ইমেল ক্ষেত্রটিকে স্যানিটাইজ করে এবং যাচাই করে:

// validate email
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
$inputs['email'] = $email;
if ($email) {
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    if (!$email) {
        $errors['email'] = 'Please enter a valid email';
    }
} else {
    $errors['email'] = 'Please enter an email';
}

এই কোড ভাল কাজ করে. যাইহোক, এটি বেশ দীর্ঘ। এছাড়াও, এটি পুনরায় ব্যবহারযোগ্য নয়। সুতরাং আসুন একটি পুনর্ব্যবহারযোগ্য বৈধতা লাইব্রেরি তৈরি করি।

বৈধতা নিয়ম সংজ্ঞায়িত করুন

প্রতিটি ক্ষেত্রের এক বা একাধিক বৈধতা নিয়ম আছে। উদাহরণস্বরূপ, ইমেল ক্ষেত্রটি প্রয়োজনীয় এবং অবশ্যই একটি বৈধ ইমেল ঠিকানা হতে হবে, তাই ইমেল ক্ষেত্রের দুটি নিয়ম রয়েছে:

  • required*
  • ইমেইল

ব্যবহারকারীর নাম প্রয়োজন এবং 3 থেকে 255 অক্ষরের মধ্যে। এছাড়াও, এটিতে শুধুমাত্র অক্ষর এবং সংখ্যা থাকা উচিত। সুতরাং, ব্যবহারকারীর নাম ক্ষেত্রের তিনটি নিয়ম রয়েছে:

  • required*
  • 3 থেকে 20 অক্ষরের মধ্যে
  • আলফানিউমেরিক

ক্ষেত্রগুলির জন্য নিয়মগুলি সংজ্ঞায়িত করতে, আপনি এইরকম একটি $fields অ্যারে সংজ্ঞায়িত করতে পারেন:

$fields = [
    'email'=> 'required | email',
    'username' => 'required | alphanumeric | between: 3,255
];

$fields অ্যারের প্রতিটি উপাদানের ক্ষেত্রের নাম হিসাবে কী এবং নিয়ম হিসাবে মান রয়েছে। আপনি | দুটি নিয়ম আলাদা করার জন্য চরিত্র।

যদি একটি নিয়মের parameters থাকে, যেমন: 3, 25 এর মধ্যে, আপনি নিয়মের নাম এবং এর parameters আলাদা করতে : অক্ষরটি ব্যবহার করুন। এছাড়াও, দুটি প্যারামিটার আলাদা করতে আমরা কমা ব্যবহার করি।

আপনি নিম্নলিখিত নিয়ম তৈরি করবেন:

RuleRule nameParameterMeaning
requiredrequiredNoক্ষেত্রটি সেট করা হয়েছে এবং খালি নয়
alphanumericalphanumericNoক্ষেত্রটিতে শুধুমাত্র অক্ষর এবং সংখ্যা রয়েছে
emailemailNoক্ষেত্রটি একটি বৈধ ইমেল ঠিকানা
securesecureNoক্ষেত্রটিতে 8 থেকে 64 অক্ষর থাকতে হবে এবং কমপক্ষে একটি সংখ্যা, একটি বড় হাতের অক্ষর, একটি ছোট হাতের অক্ষর এবং একটি বিশেষ অক্ষর থাকতে হবে। এই নিয়ম পাসওয়ার্ড ক্ষেত্রের জন্য.
min: 3minএকটি পূর্ণসংখ্যা ক্ষেত্রের ন্যূনতম দৈর্ঘ্য নির্দিষ্ট করেক্ষেত্রের দৈর্ঘ্য অবশ্যই ন্যূনতম দৈর্ঘ্যের চেয়ে বেশি বা সমান হতে হবে, যেমন, 3
max: 255maxএকটি পূর্ণসংখ্যা ক্ষেত্রের সর্বাধিক দৈর্ঘ্য নির্দিষ্ট করেক্ষেত্রের দৈর্ঘ্য অবশ্যই ন্যূনতম দৈর্ঘ্যের কম বা সমান হতে হবে, যেমন, 255
same: another_fieldsameঅন্য মাঠের নামক্ষেত্রের মান অন্য_ক্ষেত্রের মানের সমান হতে হবে
between: min, maxbetweenmin এবং max হল পূর্ণসংখ্যা যা ক্ষেত্রের সর্বনিম্ন এবং সর্বোচ্চ দৈর্ঘ্য নির্দিষ্ট করেক্ষেত্রের দৈর্ঘ্য সর্বনিম্ন এবং সর্বোচ্চ এর মধ্যে হতে হবে।
unique: table, columnuniqueএকটি রিলেশনাল ডাটাবেসে কলাম এবং টেবিল। অথবা একটি NoSQL ডাটাবেসে ক্ষেত্র এবং সংগ্রহএকটি ডাটাবেসের টেবিলের কলামে ক্ষেত্রের মান অবশ্যই অনন্য হতে হবে

নিম্নলিখিত উদাহরণ নিয়ম সহ ক্ষেত্র সংজ্ঞায়িত করে:

$fields = [
    'firstname' => 'required, max:255',
    'lastname' => 'required, max: 255',
    'address' => 'required | min: 10, max:255',
    'zipcode' => 'between: 5,6',
    'username' => 'required | alphanumeric | between: 3,255 | unique: users,username',
    'email' => 'required | email | unique: users,email',
    'password' => 'required | secure',
    'password2' => 'required | same:password'
];

validate() ফাংশন

validation লাইব্রেরিতে validate() ফাংশন থাকা উচিত যা $data এবং $fields অ্যারে যাচাই করার জন্য ডেটার একটি অ্যাসোসিয়েটিভ অ্যারে গ্রহণ করে যাতে validation এর নিয়ম রয়েছে:

function validate(array $data, array $fields)

এটি একটি অ্যারে ফেরত দেবে যাতে বৈধতা ত্রুটি রয়েছে, যেখানে প্রতিটি উপাদানের কী হল ক্ষেত্রের নাম এবং মান হল ত্রুটি বার্তা:

function validate(array $data, array $fields): array
{
    // implementation
}

validate() ফাংশনটি $ ফিল্ডের উপর পুনরাবৃত্তি করতে হবে। প্রতিটি ক্ষেত্রের জন্য, এটি নিয়মের মধ্য দিয়ে লুপ করে এবং প্রতিটি নিয়মের বিপরীতে মান যাচাই করে। বৈধতা ব্যর্থ হলে, এটি একটি $errors অ্যারেতে একটি ত্রুটি বার্তা যোগ করবে:

function validate(array $data, array $fields) : array
{
    $errors = [];

    foreach ($fields as $field => $option) {
        // get the rules of the field
        $rules = split($option);

        foreach ($rules as $rule) {
            // run a validation rule for each field
        }
    }

    return $errors;
}

যেহেতু একটি ক্ষেত্রের নিয়ম একটি স্ট্রিং, তাই আপনাকে | ব্যবহার করে নিয়মগুলি আলাদা করতে হবে চরিত্র এছাড়াও, আপনাকে সমস্ত হোয়াইটস্পেস ফালা করতে হবে। এটি করার জন্য, আপনি একটি arrow ফাংশন সংজ্ঞায়িত করতে পারেন:

  • প্রথমে, একটি বিভাজক দ্বারা একটি স্ট্রিং বিভক্ত করুন।
  • তারপর, ফলাফল অ্যারে প্রতিটি আইটেম ছাঁটা এবং এটি ফেরত.

arrow ফাংশন এই মত দেখাবে:

$split = fn($str, $separator) => array_map('trim', explode($separator, $str));

arrow ফাংশন একটি স্ট্রিং এবং একটি বিভাজক গ্রহণ করে। explode() ফাংশন $str কে $separator দ্বারা বিভক্ত করে। explode() ফাংশনের ফলাফল হল স্ট্রিং এর একটি অ্যারে।

array_map() ফাংশন প্রতিটি আইটেমের উপর trim() ফাংশন চালায় এবং হোয়াইটস্পেসগুলি সরিয়ে দিয়ে আইটেমগুলির একটি নতুন অ্যারে প্রদান করে।

validate() ফাংশনটি নিম্নরূপ তীর ফাংশন অন্তর্ভুক্ত করার জন্য আপডেট করা হয়েছে:

function validate(array $data, array $fields)
{

    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    $errors = [];

    foreach ($fields as $field => $option) {
        // get the rules of the field
        $rules =  $split($option, '|');

        foreach ($rules as $rule) {
            // run a validation on each rule
        }
    }

    return $errors;
}

$rule প্যারামিটার থাকতে পারে বা নাও থাকতে পারে। যদি এটির parameter থাকে তবে এতে : অক্ষর থাকবে। নিম্নলিখিত কোডটি নিয়মের নাম এবং এর parameters গুলি বের করে:

if (strpos($rule, ':')) {
    [$rule_name, $param_str] = $split($rule, ':');
    $params = $split($$param_str, ',');
} else {
    $rule_name = trim($rule);
}

আপনি এই কোডে $split arrow ফাংশন ব্যবহার করুন : অক্ষর দ্বারা নিয়ম বিভক্ত করতে। উদাহরণ স্বরূপ:

between: 3,255

দুটি স্ট্রিং হয়ে যাবে:

'between'
'3,255'

নিম্নলিখিতগুলি $rule_name এবং $param_str-এ $split ফাংশনের ফলাফলের প্রথম এবং দ্বিতীয় উপাদানগুলি বরাদ্দ করতে অ্যারে ডিস্ট্রাকচারিং ব্যবহার করে:

[$rule_name, $param_str] = $split($rule, ':');

উদাহরণস্বরূপ, নিয়ম “: 3, 255 এর মধ্যে” এর ফলাফল হবে:

$rule_name = 'between';
$param_str = '3, 255'

প্যারামিটার তালিকা পেতে, আপনি $param_str কে $split() ফাংশনে পাস করুন:

$params = $split($param_str, ',');

validate() ফাংশন নিচের মত দেখাবে:

function validate(array $data, array $fields): array
{
$errors = [];

$split = fn($str, $separator) => array_map('trim', explode($separator, $str));

foreach ($fields as $field => $option) {

    $rules = $split($option, '|');

    foreach ($rules as $rule) {
        $params = [];
        if (strpos($rule, ':')) {
            [$rule_name, $param_str] = $split($rule, ':');
            $params = $split($param_str, ',');
        } else {
            $rule_name = trim($rule);
        }
    }
}

return $errors;
function validate(array $data, array $fields): array
{
    $errors = [];

    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {
            $params = [];
            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }
        }
    }

    return $errors;
}

এখন, আপনার কাছে parameter সহ ক্ষেত্র এবং তাদের নিয়মের নাম রয়েছে। প্রতিটি নিয়মের জন্য বৈধতা কার্যকর করার জন্য, আপনি এই মত একটি বড় if-elseif বিবৃতি পেতে পারেন:

if($rule_name === 'required') {

} elseif($rule_name === 'email') {

} ...

যাইহোক, এই পদ্ধতির দুটি সমস্যা আছে:

  • প্রথমত, একটি বড় if-elseif বজায় রাখা কঠিন।
  • দ্বিতীয়ত, আপনি যদি একটি নতুন নিয়ম যোগ করতে চান, তাহলে আপনাকে validate() ফাংশন পরিবর্তন করতে হবে, যা আদর্শ নয়।

আপনি validate() ফাংশনটিকে আরও গতিশীল করতে চান যাতে আপনি পরে একটি নতুন নিয়ম যোগ করার সময় আমাদের ফাংশনটি পরিবর্তন করতে হবে না। এটি করতে, আপনি পরিবর্তনশীল ফাংশন ব্যবহার করতে পারেন।

প্রতিটি নিয়মের জন্য, আপনি বৈধকরণ ফাংশনটিকে গতিশীলভাবে এভাবে কল করেন:

$rule_name($data, $field, ...$params);

বৈধকরণ ফাংশনের প্রথম এবং দ্বিতীয় আর্গুমেন্ট হল $data এবং $field। তৃতীয় আর্গুমেন্ট হল $params অ্যারে থেকে ছড়িয়ে পড়া আর্গুমেন্টের একটি তালিকা।

উদাহরণস্বরূপ, যদি $params হয় [3,255], …$params 3 এবং 255 প্রদান করবে।

সুতরাং “john” মান সহ ব্যবহারকারীর নামের ‘between: 3, 255’ নিয়মটি নিম্নলিখিত ফাংশন কলে পরিণত হবে:

between($data, 'username', 3, 255)

ভেলিডেশন ফাংশন যেন স্ট্যান্ডার্ড ফাংশন যেমন min-এর সাথে কনফ্লিক্ট না করে, তা প্রতিরোধ করার জন্য আপনি আপনার ভেলিডেশন ফাংশনের নামের শুরুতে is_ যুক্ত করতে পারেন।

উদাহরণস্বরূপ, between রুলটি is_between ভেলিডেশন ফাংশন এক্সিকিউট করবে।

নিম্নলিখিত আপডেট করা validation() ফাংশন দেখায়:

function validate(array $data, array $fields): array
{
    $errors = [];

    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {
            $params = [];
            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }

            $fn = 'is_' . $rule_name;

            if (is_callable($fn)) {
                $pass = $fn($data, $field, ...$params);
            }
        }
    }

    return $errors;
}

এই validate() ফাংশনে, আপনি is_callable() ফাংশনটি ব্যবহার করে এটিকে কল করার আগে is_rule_name একটি কলযোগ্য কিনা তা পরীক্ষা করুন।

ত্রুটি বার্তা ফেরত

প্রতিটি নিয়মের একটি নির্দিষ্ট ত্রুটি বার্তা থাকা উচিত। যদি বৈধতা ব্যর্থ হয়, তাহলে আপনাকে ত্রুটির বার্তাটি $error অ্যারেতে সংরক্ষণ করতে হবে। এছাড়াও, আপনি parameter সহ একটি ত্রুটি বার্তা ফেরত দিতে সক্ষম হওয়া উচিত।

উদাহরণস্বরূপ, যদি নিম্নলিখিত নিয়ম ব্যর্থ হয়:

'username' => 'between: 3, 255'

আপনি ত্রুটি বার্তা ফেরত দেওয়া উচিত:

The username should be between 3 and 255 characters.

এটি করতে, প্রথমে, আপনি ডিফল্ট বৈধতা ত্রুটি বার্তা সংজ্ঞায়িত করুন:

const DEFAULT_VALIDATION_ERRORS = [
    'required' => 'Please enter the %s',
    'email' => 'The %s is not a valid email address',
    'min' => 'The %s must have at least %s characters',
    'max' => 'The %s must have at most %s characters',
    'between' => 'The %s must have between %d and %d characters',
    'same' => 'The %s must match with %s',
    'alphanumeric' => 'The %s should have only letters and numbers',
    'secure' => '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',
    'unique' => 'The %s already exists',
];

DEFAULT_VALIDATION_ERRORS অ্যারেতে, কী হল নিয়মের নাম, যখন মান হল ত্রুটি বার্তা৷ ত্রুটি বার্তাটিতে %s বা %d স্থানধারক রয়েছে যাতে আপনি sprintf() ফাংশনটি ব্যবহার করে ত্রুটি বার্তাটিকে এই ধরনের প্যারামিটার সহ ফর্ম্যাট করতে পারেন:

sprintf(DEFAULT_VALIDATION_ERRORS[$rule_name], $field, ...$params);

এখানে ত্রুটি বার্তা সহ validate() ফাংশন আছে:

function validate(array $data, array $fields): array
{
    $errors = [];

    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {
            $params = [];
            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }

            $fn = 'is_' . $rule_name;

            if (is_callable($fn)) {
                $pass = $fn($data, $field , ...$params);
                if (!$pass) {
                    $errors[$field] = sprintf(DEFAULT_VALIDATION_ERRORS[$rule_name], $field, ...$params);
                }
            }
        }
    }

    return $errors;
}

কাস্টম ত্রুটি বার্তা যোগ করা হচ্ছে

validate() ফাংশন ডিফল্ট ত্রুটি বার্তা ব্যবহার করে। যাইহোক, কখনও কখনও, আপনাকে আমাদের কাস্টম ত্রুটি বার্তা পাস করতে হবে।

উদাহরণস্বরূপ, আপনি ডিফল্ট ব্যবহার করার পরিবর্তে প্রয়োজনীয় নিয়মের জন্য ‘ব্যবহারকারীর নাম প্রয়োজন’ এর মতো একটি বার্তা ব্যবহার করতে চাইতে পারেন।

এটি করার জন্য, আপনি কাস্টম ত্রুটি বার্তা সংরক্ষণ করতে validate() ফাংশনে একটি তৃতীয় প্যারামিটার যোগ করতে পারেন। এই প্যারামিটার হল আইটেমগুলির একটি অ্যারে যার কী হল ক্ষেত্রের নাম এবং মান হল ত্রুটি বার্তা৷ উদাহরণ স্বরূপ:

['required' => 'The %s is required']

function validate(array $data, array $fields, array $messages = []): array
{

$split = fn($str, $separator) => array_map('trim', explode($separator, $str));

// set the validation messages
$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);

$errors = [];

foreach ($fields as $field => $option) {

    $rules = $split($option, '|');

    foreach ($rules as $rule) {

        $params = [];

        if (strpos($rule, ':')) {
            [$rule_name, $param_str] = $split($rule, ':');
            $params = $split($param_str, ',');
        } else {
            $rule_name = trim($rule);
        }

        $fn = 'is_' . $rule_name;

        if (is_callable($fn)) {
            $pass = $fn($data, $field, ...$params);
            if (!$pass) {
                $errors[$field] = sprintf($validation_errors[$rule_name], $field, ...$params);
            }
        }
    }
}

return $errors;

function validate(array $data, array $fields, array $messages = []): array
{

$split = fn($str, $separator) => array_map('trim', explode($separator, $str));

// set the validation messages
$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);

$errors = [];

foreach ($fields as $field => $option) {

    $rules = $split($option, '|');

    foreach ($rules as $rule) {

        $params = [];

        if (strpos($rule, ':')) {
            [$rule_name, $param_str] = $split($rule, ':');
            $params = $split($param_str, ',');
        } else {
            $rule_name = trim($rule);
        }

        $fn = 'is_' . $rule_name;

        if (is_callable($fn)) {
            $pass = $fn($data, $field, ...$params);
            if (!$pass) {
                $errors[$field] = sprintf($validation_errors[$rule_name], $field, ...$params);
            }
        }
    }
}

return $errors;

আপনি যদি কাস্টম ত্রুটি বার্তা অ্যারেটিকে validate() ফাংশনে পাস করেন তবে এটি ডিফল্টটির পরিবর্তে ব্যবহার করা হবে। এখানে কাস্টম ত্রুটি বার্তা সহ validate() ফাংশন রয়েছে:

function validate(array $data, array $fields, array $messages = []): array
{

    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    // set the validation messages
    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);

    $errors = [];

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {

            $params = [];

            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }

            $fn = 'is_' . $rule_name;

            if (is_callable($fn)) {
                $pass = $fn($data, $field, ...$params);
                if (!$pass) {
                    $errors[$field] = sprintf($validation_errors[$rule_name], $field, ...$params);
                }
            }
        }
    }

    return $errors;
}

validate() ফাংশনে:

প্রথমে, কাস্টম ত্রুটি বার্তাগুলির সাথে ডিফল্ট ত্রুটি বার্তাগুলিকে একত্রিত করুন৷ কাস্টম ত্রুটি বার্তাটি ডিফল্ট ত্রুটি বার্তাগুলিকে ওভাররাইট করবে:

$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $messages);

দ্বিতীয়ত, DEFAULT_VALIDATION_ERRORS অ্যারের পরিবর্তে $validation_errors থেকে ত্রুটি বার্তাগুলি পান:

$errors[$field] = sprintf($validation_errors[$rule_name], $field, ...$params);

প্রতিটি ক্ষেত্র এবং নিয়মের জন্য একটি কাস্টম ত্রুটি বার্তা যোগ করুন

এখন পর্যন্ত, একটি কাস্টম ত্রুটি বার্তা সমস্ত ক্ষেত্রের একটি নির্দিষ্ট নিয়মে প্রয়োগ করা হয়েছে৷ উদাহরণ স্বরূপ:

['required' => 'The % is required']

এবং আপনার দুটি ক্ষেত্র আছে:

[
   'username' => 'required',
   'password' => 'required'
]

কাস্টম ত্রুটি বার্তাটি ব্যবহারকারীর নাম এবং পাসওয়ার্ড উভয় ক্ষেত্রেই প্রযোজ্য হবে। কখনও কখনও, আপনি একটি নির্দিষ্ট ক্ষেত্রের জন্য একটি কাস্টম ত্রুটি বার্তা প্রয়োগ করতে চান৷ উদাহরণস্বরূপ, আপনি ব্যবহারকারীর নামের প্রয়োজনীয় নিয়মের মতো একটি বার্তা চান:

Please use your username to sign in

এবং পাসওয়ার্ড ক্ষেত্রের জন্য কাস্টম ত্রুটি বার্তা হল:

Use your password to sign in

এটি করার জন্য, আপনাকে validate() ফাংশনটি উন্নত করতে হবে:

function validate(array $data, array $fields, array $messages = []): array

একটি নির্দিষ্ট নিয়ম এবং ক্ষেত্রের জন্য একটি কাস্টম বার্তা সমর্থন করতে $messages ভেরিয়েবল নিম্নলিখিত মত দেখাবে:

[
    'required' => 'The %s is required',
    'username' => ['required'=> 'Please use your username to sign in']
]

প্রথম উপাদানটি সমস্ত ক্ষেত্রের প্রয়োজনীয় নিয়মের জন্য ত্রুটি বার্তা সেট করবে:

'required' => 'The %s is required'

এবং দ্বিতীয় উপাদানটি ব্যবহারকারীর নামের প্রয়োজনীয় নিয়মের জন্য ত্রুটি বার্তা সেট করবে:

'username' => ['required'=> 'Please use your username to sign in']

যদি উপাদানটির মান একটি স্ট্রিং হয় তবে এটি সমস্ত ক্ষেত্রের একটি নিয়মের জন্য ত্রুটি বার্তা। কী হল নিয়মের নাম, এবং মান হল একটি ত্রুটি বার্তা।

যাইহোক, যদি উপাদানটির মান একটি অ্যারে হয় তবে কীটি হল ক্ষেত্রের নাম এবং মানটি নিয়ম এবং ত্রুটি বার্তাগুলির একটি অ্যারে।

নিম্নলিখিত নিয়ম এবং ত্রুটি বার্তাগুলির একটি তালিকা ধারণ করে এমন একটি অ্যারে প্রদান করে:

$rule_messages = array_filter($messages, fn($message) =>  is_string($message));

একবার এই $rule_messages অ্যারে থাকলে, আপনি এটিকে ডিফল্ট ত্রুটি বার্তার সাথে একত্রিত করতে পারেন

$validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);

নিম্নলিখিত একটি ক্ষেত্রের জন্য ত্রুটি বার্তা পান এবং এটি বিদ্যমান থাকলে নিয়ম:

$message[$field][$rule] 

অন্যথায়, আপনি উপরের $validation_errors থেকে ত্রুটি বার্তা পেতে পারেন:

$validation_errors[$rule_name]

নিম্নলিখিত কাস্টম ত্রুটি বার্তাগুলির জন্য নতুন যুক্তি সহ validate() ফাংশন দেখায়:

/**
 * Validate
 * @param array $data
 * @param array $fields
 * @param array $messages
 * @return array
 */
function validate(array $data, array $fields, array $messages = []): array
{
    // Split the array by a separator, trim each element
    // and return the array
    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    // get the message rules
    $rule_messages = array_filter($messages, fn($message) =>  is_string($message));
    
    // overwrite the default message
    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);

    $errors = [];

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {
            // get rule name params
            $params = [];
            // if the rule has parameters e.g., min: 1
            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }
            // by convention, the callback should be is_<rule> e.g.,is_required
            $fn = 'is_' . $rule_name;

            if (is_callable($fn)) {
                $pass = $fn($data, $field, ...$params);
                if (!$pass) {
                    // get the error message for a specific field and rule if exists
                    // otherwise get the error message from the $validation_errors
                    $errors[$field] = sprintf(
                        $messages[$field][$rule_name] ?? $validation_errors[$rule_name],
                        $field,
                        ...$params
                    );
                }
            }
        }
    }

    return $errors;
}

এখন পর্যন্ত, আপনি validate() ফাংশন সম্পন্ন করেছেন। আসুন প্রতিটি নিয়মের জন্য বৈধতা ফাংশন সংজ্ঞায়িত করি।

বৈধতা ফাংশন

প্রতিটি বৈধতা ফাংশনে নিম্নলিখিত স্বাক্ষর থাকতে হবে:

function validation_function(array $data, string $field, ....$params) : bool

প্রয়োজনীয় নিয়ম

মান সেট করা থাকলে এবং খালি না থাকলে নিম্নলিখিত is_required() ফাংশনটি সত্য প্রদান করে:

function is_required(array $data, string $field): bool
{
    return isset($data[$field]) && trim($data[$field]) !== '';
}

ইমেল নিয়ম

নিম্নলিখিত is_email() ফাংশন সত্য প্রদান করে যদি মানটি একটি বৈধ ইমেল ঠিকানা হয়:

function is_email(array $data, string $field): bool
{
    if (empty($data[$field])) {
        return true;
    }

    return filter_var($data[$field], FILTER_VALIDATE_EMAIL);
}

যদি $data[$field] সেট করা না থাকে বা খালি থাকে, তাহলে is_email() ফাংশনটিও true রিটার্ন করে।

সর্বনিম্ন নিয়ম

যদি ক্ষেত্রের মানের দৈর্ঘ্য $min চেয়ে বেশি বা সমান হয় তবে নিম্নলিখিত is_min() ফাংশনটি সত্য প্রদান করে:

function is_min(array $data, string $field, int $min): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return mb_strlen($data[$field]) >= $min;
}

সর্বোচ্চ নিয়ম

নিচের is_max() ফাংশনটি সত্য প্রদান করে যদি ক্ষেত্রের মান দৈর্ঘ্য $max এর থেকে কম বা সমান হয়:

function is_max(array $data, string $field, int $max): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return mb_strlen($data[$field]) <= $max;
}

নিয়মের মধ্যে

যদি ক্ষেত্রের মানের দৈর্ঘ্য $min এবং $max এর মধ্যে হয় তাহলে নিচের is_between() ফাংশনটি সত্য হয়:

function is_between(array $data, string $field, int $min, int $max): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    $len = mb_strlen($data[$field]);
    return $len >= $min && $len <= $max;
}

আলফানিউমেরিক নিয়ম

যদি ক্ষেত্রের মানটিতে শুধুমাত্র অক্ষর বা অক্ষর থাকে তাহলে is_alphanumeric() সত্য প্রদান করে:

function is_alphanumeric(array $data, string $field): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return ctype_alnum($data[$field]);
}

একই নিয়ম

যদি ক্ষেত্রের মান অন্য ক্ষেত্রের মানের সমান হয় তাহলে is_same() ফাংশনটি সত্য প্রদান করে:

function is_same(array $data, string $field, string $other): bool
{
    if (isset($data[$field], $data[$other])) {
        return $data[$field] === $data[$other];
    }

    if (!isset($data[$field]) && !isset($data[$other])) {
        return true;
    }

    return false;
}

নিরাপদ নিয়ম

যদি ক্ষেত্রের মান অবশ্যই 8 থেকে 64 অক্ষরের মধ্যে থাকতে হবে এবং কমপক্ষে একটি সংখ্যা, একটি বড় হাতের অক্ষর, একটি ছোট হাতের অক্ষর এবং একটি বিশেষ অক্ষর থাকতে হবে তাহলে is_secure() সত্য ফেরত দেয়:

function is_secure(array $data, string $field): bool
{
    if (!isset($data[$field])) {
        return false;
    }

    $pattern = "#.*^(?=.{8,64})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\W).*$#";
    return preg_match($pattern, $data[$field]);
}

অনন্য নিয়ম

অনন্য নিয়মের জন্য, আপনার একটি ডাটাবেস সংযোগ প্রয়োজন এবং নিয়মের parameter গুলিতে নির্দিষ্ট $table $column থেকে মানটি নির্বাচন করুন। প্রথমে, কনফিগারেশন ফোল্ডারে database.php নামে একটি নতুন ফাইল তৈরি করুন এবং নিম্নলিখিত কনস্টান্টস যোগ করুন:

<?php

const DB_HOST = 'localhost';
const DB_NAME = 'auth';
const DB_USER = 'root';
const DB_PASSWORD = '';

দ্বিতীয়ত, config/database.php লোড করুন এবং ডাটাবেসের সাথে সংযোগ করার জন্য একটি ফাংশন সংজ্ঞায়িত করুন:

function db()
{
    static $pdo;
    if (!$pdo) {
        $pdo = connect(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);
    }
    return $pdo;
}

নিম্নোক্ত is_unique() ফাংশনটি সত্য প্রদান করে যদি মানটি অনন্য হয় $table $column :

function is_unique(array $data, string $field, string $table, string $column): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    $sql = "SELECT $column FROM $table WHERE $column = :value";

    $stmt = db()->prepare($sql);
    $stmt->bindValue(":value", $data[$field]);

    $stmt->execute();

    return $stmt->fetchColumn() === false;
}

সবগুলোকে একত্রে রাখ

নিম্নলিখিতটি বৈধতা লাইব্রেরিতে সমস্ত ফাংশন দেখায়:

<?php

require __DIR__ . '/../config/database.php';

const DEFAULT_VALIDATION_ERRORS = [
    'required' => 'Please enter the %s',
    'email' => 'The %s is not a valid email address',
    'min' => 'The %s must have at least %s characters',
    'max' => 'The %s must have at most %s characters',
    'between' => 'The %s must have between %d and %d characters',
    'same' => 'The %s must match with %s',
    'alphanumeric' => 'The %s should have only letters and numbers',
    'secure' => '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',
    'unique' => 'The %s already exists',
];


/**
 * Validate
 * @param array $data
 * @param array $fields
 * @param array $messages
 * @return array
 */
function validate(array $data, array $fields, array $messages = []): array
{
    // Split the array by a separator, trim each element
    // and return the array
    $split = fn($str, $separator) => array_map('trim', explode($separator, $str));

    // get the message rules
    $rule_messages = array_filter($messages, fn($message) => is_string($message));
    // overwrite the default message
    $validation_errors = array_merge(DEFAULT_VALIDATION_ERRORS, $rule_messages);

    $errors = [];

    foreach ($fields as $field => $option) {

        $rules = $split($option, '|');

        foreach ($rules as $rule) {
            // get rule name params
            $params = [];
            // if the rule has parameters e.g., min: 1
            if (strpos($rule, ':')) {
                [$rule_name, $param_str] = $split($rule, ':');
                $params = $split($param_str, ',');
            } else {
                $rule_name = trim($rule);
            }
            // by convention, the callback should be is_<rule> e.g.,is_required
            $fn = 'is_' . $rule_name;

            if (is_callable($fn)) {
                $pass = $fn($data, $field, ...$params);
                if (!$pass) {
                    // get the error message for a specific field and rule if exists
                    // otherwise get the error message from the $validation_errors
                    $errors[$field] = sprintf(
                        $messages[$field][$rule_name] ?? $validation_errors[$rule_name],
                        $field,
                        ...$params
                    );
                }
            }
        }
    }

    return $errors;
}

/**
 * Return true if a string is not empty
 * @param array $data
 * @param string $field
 * @return bool
 */
function is_required(array $data, string $field): bool
{
    return isset($data[$field]) && trim($data[$field]) !== '';
}

/**
 * Return true if the value is a valid email
 * @param array $data
 * @param string $field
 * @return bool
 */
function is_email(array $data, string $field): bool
{
    if (empty($data[$field])) {
        return true;
    }

    return filter_var($data[$field], FILTER_VALIDATE_EMAIL);
}

/**
 * Return true if a string has at least min length
 * @param array $data
 * @param string $field
 * @param int $min
 * @return bool
 */
function is_min(array $data, string $field, int $min): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return mb_strlen($data[$field]) >= $min;
}

/**
 * Return true if a string cannot exceed max length
 * @param array $data
 * @param string $field
 * @param int $max
 * @return bool
 */
function is_max(array $data, string $field, int $max): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return mb_strlen($data[$field]) <= $max;
}

/**
 * @param array $data
 * @param string $field
 * @param int $min
 * @param int $max
 * @return bool
 */
function is_between(array $data, string $field, int $min, int $max): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    $len = mb_strlen($data[$field]);
    return $len >= $min && $len <= $max;
}

/**
 * Return true if a string equals the other
 * @param array $data
 * @param string $field
 * @param string $other
 * @return bool
 */
function is_same(array $data, string $field, string $other): bool
{
    if (isset($data[$field], $data[$other])) {
        return $data[$field] === $data[$other];
    }

    if (!isset($data[$field]) && !isset($data[$other])) {
        return true;
    }

    return false;
}

/**
 * Return true if a string is alphanumeric
 * @param array $data
 * @param string $field
 * @return bool
 */
function is_alphanumeric(array $data, string $field): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    return ctype_alnum($data[$field]);
}

/**
 * Return true if a password is secure
 * @param array $data
 * @param string $field
 * @return bool
 */
function is_secure(array $data, string $field): bool
{
    if (!isset($data[$field])) {
        return false;
    }

    $pattern = "#.*^(?=.{8,64})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\W).*$#";
    return preg_match($pattern, $data[$field]);
}


/**
 * Connect to the database and returns an instance of PDO class
 * or false if the connection fails
 *
 * @return PDO
 */
function db(): PDO
{
    static $pdo;
    // if the connection is not initialized
    // connect to the database
    if (!$pdo) {
        $pdo = new PDO(
            sprintf("mysql:host=%s;dbname=%s;charset=UTF8", DB_HOST, DB_NAME),
            DB_USER,
            DB_PASSWORD,
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
        );
    }
    return $pdo;
}

/**
 * Return true if the $value is unique in the column of a table
 * @param array $data
 * @param string $field
 * @param string $table
 * @param string $column
 * @return bool
 */
function is_unique(array $data, string $field, string $table, string $column): bool
{
    if (!isset($data[$field])) {
        return true;
    }

    $sql = "SELECT $column FROM $table WHERE $column = :value";

    $stmt = db()->prepare($sql);
    $stmt->bindValue(":value", $data[$field]);

    $stmt->execute();

    return $stmt->fetchColumn() === false;
}

validation লাইব্রেরি পরীক্ষা করা হচ্ছে

অনন্য নিয়ম পরীক্ষা করার জন্য, আপনাকে একটি নতুন ডাটাবেস এবং ব্যবহারকারীর নাম ক্ষেত্র সহ একটি টেবিল তৈরি করতে হবে, উদাহরণস্বরূপ।

প্রথমে, auth নামে একটি নতুন ডাটাবেস তৈরি করুন:

CREATE DATABASE auth;

দ্বিতীয়ত, একটি নতুন ব্যবহারকারীর টেবিল তৈরি করুন:

CREATE TABLE users(
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL UNIQUE,
    email VARCHAR(300) NOT NULL UNIQUE
);

নোট করুন যে পরীক্ষার উদ্দেশ্যে, আমাদের পাসওয়ার্ড ক্ষেত্র থাকা দরকার নেই।

তৃতীয়, ব্যবহারকারীদের টেবিলে একটি সারি সন্নিবেশ করান:

<?php

require __DIR__ . '/validation.php';

$data = [
    'firstname' => '',
    'username' => 'bob',
    'address' => 'This is my address',
    'zipcode' => '999',
    'email' => 'jo@',
    'password' => 'test123',
    'password2' => 'test',
];



$fields = [
    'firstname' => 'required, max:255',
    'lastname' => 'required, max: 255',
    'address' => 'required | min: 10, max:255',
    'zipcode' => 'between: 5,6',
    'username' => 'required | alphanumeric | between: 3,255 | unique: users,username',
    'email' => 'required | email | unique: users,email',
    'password' => 'required | secure',
    'password2' => 'required | same:password'
];


$errors = validate($data, $fields, [
    'required' => 'The %s is required',
    'password2' => ['same'=> 'Please enter the same password again']]
);

print_r($errors);

আউটপুট:

Array
(
    [firstname] => The firstname is required
    [lastname] => The lastname is required
    [zipcode] => The zipcode must have between 5 and 6 characters
    [username] => The username already exists
    [email] => The email is not a valid email address
    [password] => The password must have between 8 and 64 characters and contain at least one number, one upper case letter, one lower case letter and o
ne special character
    [password2] => Please enter the same password again
)

একটি নতুন বৈধতা নিয়ম যোগ করা হচ্ছে

একটি নতুন নিয়ম যোগ করতে, আপনাকে দুটি জিনিস করতে হবে: প্রথমে, DEFAULT_VALIDATION_ERRORS অ্যারেতে একটি ডিফল্ট ত্রুটি বার্তা যোগ করুন৷

const DEFAULT_VALIDATION_ERRORS = [
    // ...
    new_rule => "Error message for the new rule"

];

দ্বিতীয়ত, নিম্নলিখিত স্বাক্ষর সহ একটি বৈধতা ফাংশন সংজ্ঞায়িত করুন:

function is_new_rule(array $data, string $field, ....$params) : bool

এই টিউটোরিয়ালে, আপনি শিখেছেন কিভাবে PHP-তে পুনরায় ব্যবহারযোগ্য বৈধতা লাইব্রেরি তৈরি করতে হয়।

Leave a Comment

Share this Doc

PHP বৈধতা (Validation)

Or copy link

CONTENTS

Subscribe

×
Cancel