آموزش PHP (فصل ۳)

آشنایی با دستورات شرطی if elseif else در زبان PHP


فارغ از نوع وب‌ اپلیکیشنی که بخواهیم طراحی کنیم، همواره نیاز به بررسی شروط مختلف در اپلیکیشن وجود دارد که چنین چیزی در زبان PHP با استفاده از دستوارت elseif ،if و else مدیریت می‌شود:

if (First condition) {
    // Do something
} elseif (Second condition) {
    // Do something else
} else {
    // Do something if none of the above is met
}

آنچه در بالا مشاهده می‌شود، ساختار کلی دستورات شرطی در زبان PHP است. در واقع، اگر شرط قرار گرفته داخل پرانترهای مرتبط با if برآورده شود (یا به عبارت دیگر true یا درست باشد)، کدهای قرار گرفته داخل { } اجرا خواهند شد و دستورات elseif و else هرگز اجرا نخواهند شد اما اگر این شرط برآورده نشود، مفسر به سراغ شرط قرار گرفته داخل پرانترهای مرتبط با دستور elseif می‌رود و اگر این شرط برآورده شد، کدهای قرار گرفته داخل { } اجرا خواهند شد و مفسر هرگز به سراغ دستور else نمی‌رود اما اگر این شرط هم برآورده نشد، در نهایت مفسر هر آنچه که داخل { } مرتبط با else قرار گرفته باشد را اجرا خواهد کرد. توجه داشته باشیم که به هر تعداد elseif که بخواهیم می‌توانیم در بلوک شرطی خود بگنجانیم:

if (First condition) {
    // Do something
} elseif (Second condition) {
    // Do something else
} elseif (Third condition) {
    // Do something else
} elseif (Forth condition) {
    // Do something else
} elseif (Fifth condition) {
    // Do something else
} elseif (Sixth condition) {
    // Do something else
} elseif (Nth condition) {
    // Do something else
} else {
    // Do something if none of the above is met
}

گرچه به هر تعدادی که بخواهیم می‌توانیم از دستورات elseif استفاده کنیم، اما در میان دولوپرهای PHP مرسوم است که در چنین شرایطی از ساختار شرطی دیگری تحت عنوان switch استفاده می‌کنند که در آموزش‌های آتی به تفصیل مورد بررسی قرار خواهد گرفت.

در ارتباط با دستورات شرطی، بایستی این نکته را مد نظر داشته باشیم که دستورات elseif و else دلخواه هستند و می‌توانیم هرگز از آنها استفاده نکنیم. به عبارت دیگر داریم:

if (Condition) {
    // Do something
}

در واقع، در اسکریپت فوق چک می‌کنیم ببینیم که آیا Condition (شرط) برابر با true است یا خیر؛ اگر true باشد، دستورات داخل { } اجرا خواهند شد و در غیر این صورت، هیچ اتفاق دیگری رخ نخواهد داد. علاوه بر این، اگر بخواهیم می‌توانیم علائم { } را برای ساده‌تر سورس‌کد حذف کنیم:

if (Condition)
    // Do something

در این نوع ساختار توجه داشته باشیم که صرفاً اولین خط کدی که پس از دستور if قرار گرفته است به عنوان بلوک if در نظر گرفته خواهد شد و خطوط بعدی خارج از این ساختار تلقی خواهند شد. برای روشن‌تر شدن این مسئله داریم:

if (Condition)
    // Do something
    // Do something else

در واقع اگر شرط true باشد، هرآنچه کدی که به جای کامنت Do something // قرار گرفته باشد اجرا خواهد شد و هرآنچه کدی که به جای کامنت Do something else // قرار گرفته باشد فارغ از این که شرط true یا false باشد، اجرا خواهد شد. هشدارتوجه داشته باشیم که حذف علائم { } می‌تواند منجر ناخوانی سورس‌کد گردد. لذا توصیه می‌شود که همواره از علائم { } استفاده شود.

اگر بخواهیم زمانی که از دستور elseif استفاده می‌کنیم علائم { } را حذف کنیم، بایستی به صورت زیر کدهای خود را ریفکتور کنیم:

if (First condition):
    // Do something
elseif (Second condition):
    // Do something else
else:
    // Do something if none of the above is met
endif;

می‌بینیم که ساختار تا حدودی متفاوت است و کلیدواژهٔ جدیدی تحت عنوان endif استفاده شده است.به خاطر داشته باشیدلازم به ذکر است که کلیدواژهٔ elseif را هم می‌شود سرهم (elseif) و هم جدا (else if) نوشت. البته این در شرایطی صادق است که از علائم { } استفاده کرده باشیم و چنانچه این علائم را حذف کرده باشیم‌، صرفاً بایستی این کلیدواژه را سرهم (elseif) نوشت که در غیر این صورت ارور خواهیم گرفت.

در ارتباط با نکتهٔ مهم فوق داریم:

if (First condition):
    // Do something
else if (Second condition): // Pay attention to the space between else and if
    // Do something else
else:
    // Do something if none of the above is met
endif;

اگر ساختار فوق را در کدهای واقعی به کار گیریم و اسکریپت را اجرا کنیم، با ارور زیر مواجه خواهیم شد:

Parse error: syntax error, unexpected 'if' (T_IF), expecting ':' in /var/www/sokanacademy-php-course/index.php on line 4

در چه شرایطی دستورات مرتبط با if اجرا خواهند شد؟
به طور کلی،‌ چنانچه نتیجهٔ یک Condition (شرط) اصطلاحاً true باشد، دستورات مرتبط با if اجرا خواهند شد. به طور مثال داریم:

<?php
$condition = '';
if ($condition) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

مقدار متغیر condition$ را برابر با یک استرینگ خالی قرار داده‌ایم. حال اگر اسکریپت فوق را اجرا کنیم، از آنجا که از دید مفسر PHP استرینگ خالی برابر با false است، دستور داخل else اجرا خواهد شد. به عنوان مثالی دیگر داریم:

<?php
$condition = 0;
if ($condition) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

کماکان مقدار 0 هم برابر با false است و دستور داخل else اجرا خواهد شد. به عنوان مثالی دیگر داریم:

<?php
$condition = false;
if ($condition) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

مقدار false که برای متغیر condition$ در نظر گرفته شده است هم کاملاً مشخص است که نیاز if را برآورده نمی‌سازد. به عنوان مثالی دیگر داریم:

<?php
$condition = null;
if ($condition) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

پیش از این گفتیم که NULL یکی از انواع دیتاتایپ‌ها در زبان PHP است و این دیتاتایپ هم رفتاری همچون false دارد و نمی‌تواند نیاز دستور شرطی if را برآورده سازد. حال اگر مقادیری همچون موارد زیر را در نظر بگیریم، به سادگی خواهیم توانست وارد دستور شرطی if شویم:

<?php
$condition = true;
/*
Or alternatively
$condition = 1; or
$condition = "This is set";
*/
if ($condition) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

به عنوا خروجی اسکریپت فوق داریم:

The condition is met

در واقع، اگر به جای مقدار true برای متغیر condition$ از مقادیری همچون ۱ و یا استرینگ This is set استفاده کنیم، همواره شرط if برابر با true بوده و دستورات داخل علائم { } مرتبط با if اجرا خواهند شد (لازم به ذکر است که ۱ نمود عددی مقدار true و ۰ نمود عددی مقدار false است).

کاربرد فانکشن ()isset در کنار دستورات شرطی
پیش از این با فانکشن ()isset آشنا شدیم و گفتیم کاری که این تابع انجام می‌دهد این است که چک می‌کند ببیند آیا یک متغیر مقداری به غیر از NULL دارد یا خیر؛ اگر این‌گونه بود، مقدار true را بازمی‌گرداند و اگر هم NULL بود مقدار false را باز خواهد گرداند. به عنوان مثال داریم:

<?php
$condition = 0;
if (isset($condition)) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

اگر اسکریپت فوق را اجرا کنیم‌، می‌بینیم که دستور مرتبط با if اجرا می‌گردد بدان معنی که خروجی فانکشن ()isset برابر با true است و این در حالی است که اگر خود متغیر condition$ را به عنوان پارامتر ورودی به دستور if پاس دهیم، از دید مفسر PHP هرگز true نیست!

به عبارت دیگر، مقادیر false ،0 و استرینگ خالی که پیش از این چک کردیم که حاوی مقدار false بودند، اگر با استفاده از فانکشن ()isset به کار گرفته شوند، مقدار true بازگردانده خواهد شد و تنها چیزی که مقدار false را باز خواهد گرداند، دیتاتایپ NULL است. به عنوان مثال داریم:

<?php
$condition;
if (isset($condition)) {
    echo "The condition is met";
} else {
    echo "The condition is not met";
}

باتوجه به این که متغیر condition$ تعریف شده ولی مقداردهی نشده است (یا به عبارت دیگر Set نشده است)، خروجی فانکشن ()isset برابر با false بود، فلذا دستور داخل else اجرا خواهد شد.

استفاده از اپراتورهای منطقی و مقایسه‌ای در دستورات شرطی
پیش از این با اپراتورهای منطقی و مقایسه‌ای در زبان PHP آشنا شدیم و این در حالی است که به سادگی می‌توان از این اپراتورها در دستورات شرطی if استفاده کرد:

اپراتورتوضیحات
==برابری را نشان می‌دهد.
===برابری و دیتاتایپ یکسان را نشان می‌دهد.
=! یا <>نابرابری را نشان می‌دهد.
==!نابرابری و عدم برخورداری از دیتاتایپ یکسان را نشان می‌دهد.
<بزرگ‌تر بودن را نشان می‌دهد.
>کوچک‌تر بودن را نشان می‌دهد.
=<بزرگ‌تر یا مساوی را نشان می‌دهد.
=>کوچک‌تر یا مساوی را نشان می‌دهد.
and یا &&این اپراتور به معنی «و» است و چنانچه دو طرف آن true باشد، مقدار true بازگردانده خواهد شد.
or یا ||این اپراتور به معنی «یا» است و چنانچه یکی از عملوندهای راست یا چپ این اپراتور true باشد، مقدار true بازگردانده خواهد شد.
xor یا ^در صورتی که یکی از عملوندها true باشد (نه هر دوی آنها)، این اپراتور مقدار true را باز خواهد گرداند.
!این اپراتور مقدار true را باز خواهد گرداند چنانچه عملوند قرار گرفته پس از آن true نباشد!

برای روشن‌تر شدن بحث، اپراتور مقایسه‌ای == را در یک دستور شرطی مورد استفاده قرار داده‌ایم تا مشخص سازیم که آیا پروتکل انتخابی ما امن (https) است یا ناامن (http). برای این منظور داریم:

<?php
$protocol = 'http';
if ($protocol == 'http') {
    echo "Your connection is insecure!";
} elseif ($protocol == 'https') {
    echo "Let`s go. You have a secure connection.";
} else {
    echo "The protocol in undefined!";
}

همان‌طور که ملاحظه می‌شود، متغیری تعریف کرده‌ایم تحت عنوان protocol$ که استرینگی به صورت http داخل آن ذخیره کرده‌ایم. سپس با استفاده از دستورات شرطی if elseif else به بررسی مقدار این متغیر پرداخته‌ایم. 

در واقع، دستور داده‌ایم که اگر مقدار این متغیر برابر با http بود، عبارت !Your connection is insecure در خروجی چاپ شود، اگر https بود عبارت .Let`s go. You have a secure connection چاپ شده و در نهایت اگر نه http بود و نه https، عبارت !The protocol in undefined در معرض دید کاربر قرار گیرد. به طور مثال، اگر اسکریپت فوق را در مرورگر اجرا کنیم، با خروجی زیر مواجه خواهیم شد:

Your connection is insecure!

به عنوان مثالی دیگر، می‌توان نحوهٔ به‌کارگیری اپراتور || به معنی «یا» را مورد بررسی قرار دهیم:

<?php
$experience = 4;
$levelOfProficiency = 'senior';
$age = 27;

if (($experience > 5 || $levelOfProficiency == 'senior') && ($age > 20 && $age < 35)) {
    echo "You might be a developer with a high salary.";
} else {
    echo "Although you can find a job, you don`t have to expect a high salary.";
}

همان‌طور که ملاحظه می‌شود، سه متغیر تعریف کرده‌ایم تحت عناوین levelOfProfiency ،$experience$  و age$ که به ترتیب به معانی «تجربه»، «سطح مهارت» و «سن» هستند. دستور شرطی استفاده شده در کد فوق کمی پیچیده به نظر می‌رسد اما گاهی‌اوقات نیاز به استفاده از ساختارهایی این‌چنین داریم.

در واقع، در دستور if دو شرط مختلف را سنجیده‌ایم اما برای اینکه خوانایی سورس‌کد بالا رود (و احیاناً به تناقض برنخوریم)، آنها را داخل پرانتزهایی جداگانه‌ای قرار داده و مابین هر دو جفت پرانتز هم از علامت && استفاده کرده‌ایم بدین معنا که هر دو شرط بایستی true باشند.

در پرانتز اول، گفته‌ایم که میزان تجربهٔ دولوپر باید بیش از ۵ سال باشد یا سطح مهارت ایشان برابر با senior (ارشد) باشد. در پرانتز دوم هم گفته‌ایم که سن دولوپر بایستی بزرگ‌تر از ۲۰ و کوچک‌تر از ۳۵ سال باشد. حال اسکریپت فوق را اجرا می‌کنیم:

You might be a developer with a high salary.

می‌بینیم که کلیهٔ شروط true هستند، لذا دستور داخل بلوک if اجرا می‌شود و این در حالی است که مثلاً اگر سن دولوپر فرضی را ۲۰ در نظر بگیریم، شروط برآورده نشده و دستور داخل بلوک else اجرا می‌گردد:

<?php
$experience = 4;
$levelOfProficiency = 'senior';
$age = 20;

if (($experience > 5 || $levelOfProficiency == 'senior') && ($age > 20 && $age < 35)) {
    echo "You might be a developer with a high salary.";
} else {
    echo "Although you can find a job, you don`t have to expect a high salary.";
}

به عنوان خروجی داریم:

Although you can find a job, you don`t have to expect a high salary.

واقعیت امر آن است که در دستور شرطی خود در پرانتز دوم گفته‌ایم که حداقل سن بایستی بیش از ۲۰ سال باشد و از آنجا که سن این دولوپر فرضی برابر با ۲۰ است، شراط برآورده نشده و در نتیجه وارد بلوک else می‌شویم.

دستورات شرطی اصطلاحاً Nested (تو در تو)
بسته به میزان پیچیدگی اسکریپتی که می‌نویسیم، گاهی‌اوقات نیاز داریم تا چندین دستور شرطی را با یکدیگر ادغام کنیم تا بتوانیم شرایط مختلفی را ساپورت کنیم. در چنین موقعیت‌هایی می‌بایست با مفهومی تحت عنوان Nested If Statements (دستورات شرطی تو در تو) آشنا شویم. برای روشن‌تر شدن این مبحث، کدهای زیر را مد نظر قرار می‌دهیم:

<?php
$experience = 4;
$levelOfProficiency = 'senior';
$age = 31;

if (($experience > 5 || $levelOfProficiency == 'senior') && ($age > 20 && $age < 35)) {
    if ($age > 20 && $age <= 25) {
        echo "Although you`re so young, you might be a developer with a high salary.";
    } elseif ($age > 26 && $age <= 30) {
        echo "You might be a developer with a high salary. So you can get ready to get married.";
    } else {
        echo "Although you might be a developer with a high salary, you`re getting old.";
    }
} else {
    echo "Although you can find a job, you don`t have to expect a high salary.";
}

ابتدا اسکریپت فوق را اجرا می‌کنیم:

Although you might be a developer with a high salary, you`re getting old.

در واقع، به خاطر true بودن شروط، ابتدا وارد بلوک if اصلی (خارجی) می‌شویم اما در ارتباط با دستورات شرطی داخلی، از آنجا که شروط داخل بلوک‌های if و elseif داخلی برآورده نشده‌اند، وارد بلوک else داخلی شده‌ایم.

آشنایی با اپراتور ? به جای دستورات if else در PHP
پیش از این در بحث معرفی اپراتورها، به معرفی اپراتور ? که تحت عنوان Ternary Operator شناخته می‌شود پرداختیم و گفتیم که از این اپراتور به منظور خلاصه‌نویسی دستورات شرطی if else استفاده می‌شود. برای مثال داریم:

<?php
$experience = 2;
$levelOfProficiency = 'senior';
$hasHighSalary = null;
$hasHighSalary = ($experience >= 4 && $levelOfProficiency == 'senior') ? true : false;
var_dump($hasHighSalary);

به عنوان خروجی اسکریپت فوق داریم:

bool(false)

در واقع، متغیری تعریف کرده‌ایم تحت عنوان hasHighSalary$ (دارای حقوق بالا) که مقدار پیش‌فرض آن را برابر با null قرار داده‌ایم که یکی از دیتاتایپ‌های زبان PHP است. سپس در خط بعد مقدار این متغیر را برابر با یک دستور شرطی با استفاده از اپراتور ? قرار داده‌ایم بدین صورت که گفته‌ایم اگر تجربهٔ دولوپر بزرگ‌تر یا مساوی با ۴ سال بود و سطح مهارت وی senior (ارشد) بود، مقدار بولینی true برای این متغیر در نظر گرفته شود و در غیر این صورت، مقدار false اختصاص یابد و از آنجا که تجربهٔ این دولوپر فرضی برابر با ۲ سال است، می‌بینیم که به درستی مقدار false برای این متغیر در نظر گرفته شده است.

علاوه بر Ternary Operator، در نسخهٔ ۷ زبان PHP اپراتور دیگری معرفی شد به نام Null Coalescing که در پستی در وبلاگ سکان آکادمی تحت عنوان آشنایی با اپراتور Null Coalesce در PHP نسخهٔ ۷ این اپراتور به تفصیل مورد بررسی قرار گرفته است.

چک کردن دیتای فرم‌های HTML با دستورات شرطی در زبان PHP


فرم‌ها یکی از بخش‌های لاینفک وب اپلیکیشن‌ها هستند به طوری که برای ثبت‌نام، نظردهی و کارهای به مراتب بیشتری مورد استفاده قرار می‌‌گیرند. یکی از کاربردهای دستورات شرطی if که در آموزش گذشته با آن آشنا شدید، چک کردن دیتا فرم‌های HTML است که در این آموزش پس از آشنایی با نحوهٔ ساخت یک فرم نظرسنجی، یاد خواهید گرفت که چگونه با استفاده از دستورات if else می‌توان داده‌های ارسالی توسط کاربران را مورد بررسی قرار داده و از پر بودن کلیهٔ فلیدها اطمینان حاصل کرد.

اگرچه آموزش ترفندهای HTML خارج از سرفصل‌های آموزشی این دوره است، اما به منظور درک بهتر سازوکار فرم‌ها، در ادامه اقدام به نوشتن یک فرم نظردهی کرده سپس بخش‌های مهم آن را توضیح خواهیم داد:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Simple HTML Form</title>
</head>
<body>
  <form action="handle_form.php" method="POST">
    Your name: <br>
    <input type="text" name="name"><br>

    <br> Your email: <br>
    <input type="text" name="email"><br>

    <br> Your gender: <br>
    <input type="radio" name="gender" value="male"> Male<br>
    <input type="radio" name="gender" value="female"> Female<br>

    <br> Your age: <br>
    <select name="age">
        <option value="10-20">10-20</option>
        <option value="20-30">20-30</option>
        <option value="30-40">30-40</option>
        <option value="40-50">40-50</option>
        <option value="50-60">50-60</option>
        <option value="60-70">60-70</option>
        <option value="70-80">70-80</option>
    </select>

    <br> Your comments: <br>
    <textarea name="comment" rows="15" cols="50"></textarea><br><br>
    <input type="submit" value="Submit">
  </form>
</body>
</html>

کدهای فوق را می‌توانیم در فایلی تحت عنوان form.html ذخیره سازیم.به خاطر داشته باشیدآنچه در نامگذاری این فرم حائز اهمیت می‌باشد این است که با توجه به اینکه هیچ نوع کد PHP داخل این فایل نیست، به سادگی می‌توانیم پسوند html. را برای آن انتخاب کنیم (البته اگر این فایل را با پسوند php. نیز ذخیره سازیم هیچ مشکلی پیش نخواهد آمد).

در اسکریپت فوق دو اتریبیوت وجود دارد که بسیار حائز اهمیت هستند که عبارتند از action و method. کاری که Value (مقدار) در نظر گرفته شده برای اتریبیوت action انجام می‌دهد این است که حاوی آدرس صفحه‌ای است که اسکریپت PHP مد نظرمان که قرار است دیتای فرم را هَندل کند در آن قرار دارد؛ اتریبیوت method هم -همان‌طور که از نامش مشخص است- متد یا روشی که قرار است این فرم هَندل شود را مشخص می‌سازد که یا می‌تواند GET باشد و یا POST.

آشنایی با تفاوت‌های متدهای GET و POST
مقدار اتریبیوت method یکی از متدهای پروتکل HTTP است که هر کدام خصوصیات و بالتبع کاربردهای خاص خود را دارند که در ادامه بیشتر پیرامون این تفاوت‌ها بحث خواهیم کرد.

متد GET دیتای ارسالی توسط فرم HTML را در قالب یکسری Name-Value (نام-مقدار) از طریق URL برای اسکریپت مد نظر ارسال می‌کند. به عنوان مثال داریم:

http://www.example.com/script.php?name=Behzad&gender=M

همان‌طور که در URL فوق مشخص است، پس از نام اسکریپت مد نظر (script.php) یک علامت ? قرار داده سپس دیتای مد نظر خود را در قالب دو جفت Name-Value که با علامت & از یکدیگر جدا شده‌اند ارسال کرده‌ایم.

در واقع، دو پارامتر به نام‌های name و gender داریم که به ترتیب مقادیر Behzad و M برای آنها در نظر گرفته شده است. به طور کلی، مزایای متد GET عبارتند از:
– پس از استفاده از این متد، می‌توان URL را در مرورگر بوکمارک کرد.
– بدون از دست رفتن دیتا، می‌توان صفحه را رِفرش کرد.

در عین حال، این متد یکسری نقاط ضعف هم دارا است که عمده‌ترین آنها عبارتند از:
– دیتای حجیمی را نمی‌توان با استفاده از این متد به سمت سرور ارسال کرد.
– دیتای ارسالی به سمت سرور قابل رؤیت است.
– زمان‌هایی که امنیت دیتای ارسالی زیاد است، این متد کارایی ندارد.

با این تفاسیر، می‌شود گفت که می‌توان از متد GET زمان‌هایی استفاده کرد که صرفاً بخواهیم یکسری داده‌ها را از دیتابیس فراخوانی کنیم و یا یکسری پارامتر را از صفحه‌ای به صفحهٔ دیگر پاس (انتقال) دهیم.

در مقابل، از متد POST زمان‌هایی می‌توانیم استفاده کنیم که:
– حجم دیتای ارسالی بسیار زیاد است.
– امنیت داده‌ها بالا است.

در فرم فوق، از آنجا که قصد داریم دیتای نسبتاً زیادی برای اسکریپتی که در فایل handle_form.php وجود دارد ارسال کنیم، از متد POST استفاده کرده‌ایم.به خاطر داشته باشیدنوشتن مقادیر اتریبیوت method هم می‌تواند با حروف کوچک باشد و هم با حروف بزرگ؛ به عبارت دیگر، هم می‌توان به صورت get/post و هم GET/POST آنها را نوشت اما روال نوشتن با حروف بزرگ است.

چیزی که در ارتباط با فرم فوق باید مد نظر قرار داد، نام یکسان برای فیلد gender است. در حقیقت، نام یکسان gender برای هر دو فیلد مربوطه این امکان را برای کاربر فراهم می‌آورد تا بتواند فقط و فقط یکی از آیتم‌ها را انتخاب کند. در حقیقت اگر بخش مربوط به انتخاب جنسیت در فرم فوق را به صورت زیر ریفکتور کنیم:

<input type="radio" name="gender_one" value="male"> Male<br>
<input type="radio" name="gender_two" value="female"> Female<br>

همان‌طور که مشاهده می‌شود، برای اتریبیوت‌های name از نام‌های مختلفی همچون gender_one و gender_two استفاده شده که این امکان را در اختیار ما قرار خواهند داد که بتوانیم در آن واحد هر دو گزینه را انتخاب کنیم.

یکی از مزیت‌های زبان PHP این است که تعامل بسیار خوبی با زبان HTML دارد و همین قضیه موجب گردیده کار با آن بسیار آسان گردد. در ادامه، برای اینکه بتوانیم دیتای فرم را با استفاده از زبان PHP هَندل کنیم، فایلی می‌سازیم تحت عنوان handle_form.php حاوی کدهای زیر:

<?php
$name = $_REQUEST['name'];
$email = $_REQUEST['email'];
$gender = $_REQUEST['gender'];
$age = $_REQUEST['age'];
$comment = $_REQUEST['comment'];

echo "Your name is: $name;<br> Your email is: $email;<br> Your gender is: $gender;<br> Your age is: $age;<br> Your comment is: $comment";

پیش از این، به طور خیلی خلاصه با مفهوم متغیرهای اصطلاحاً Super Global آشنا شدیم که یکی از آنها REQUEST_$ است که این وظیفه را دارا است تا کلیهٔ دیتای ارسال شده توسط فرم‌ها (حاوی متدهای GET و POST) را در خود ذخیره سازد.

نکته‌ای که در اینجا باید توجه ویژه‌ای به آن کرد این است که مقادیر (کلیدهای) در نظر گرفته شده در REQUEST_$ دقیقاً می‌بایست با مقادیری که برای اتریبیوت name در فیلدهای فرم انتخاب کردیم، یکسان باشد. به عبارت دیگر، اگر برای فیلد مرتبط با ایمیل کاربر مقداری همچون email را برای اتریبیوت name در نظر گرفته باشیم، در اسکریپت PHP خود نیز باید به شکل زیر به آن دست یابیم:

$_REQUEST['email']

و چنانچه این کلید را با حرف اول بزرگ و به شکل Email بنویسیم، با هشداری به صورت زیر مواجه خواهیم شد:

Notice: Undefined index: Email in /var/www/sokanacademy-php-course/03/03-form/handle_form.php on line 2

حال کلیهٔ فیلدهای فرم فوق را پر کرده و روی دکمهٔ Submit کلیک می‌کنیم:

Your name is: Behzad;
Your email is: behzad.moradi@example.com;
Your gender is: male;
Your age is: 30-40;
Your comment is: This is my first comment.

می‌بینیم که توانستیم کلیهٔ مقادیر فرم را بگیریم. کاری که در اینجا انجام داده‌ایم، صرفاً پرینت کردن مقادیر روی صفحه است و این در حالی است که می‌توان این مقادیر را برای کاربر خاصی ایمیل کرد و آیا آن‌ها را در دیتابیس ذخیره ساخت که در فصول آینده بیشتر پیرامون این مباحث توضیح خواهیم داد. نکتهدر ارتباط با تست این فرم می‌بایست دو نکته را مد نظر داشته باشیم و آن هم این که محل قرارگیری فایل handle_form.php دقیقاً‌ می‌بایست در همان پوشه‌ای باشد که فایل form.html قرار گرفته است. همچنین این فرم را باید از طریق لوکال‌هاست تست کرد و در غیر این صورت، اسکریپت PHP اجرا نخواهد شد. 

اکنون قصد داریم یک بار دیگر فرم نظرسنجی فوق را اصطلاحاً Submit (ارسال) کنیم اما بدون این که هیچ‌کدام از فیلدهای این فرم را پر کنیم یا انتخاب کنیم:

Notice: Undefined index: gender in /var/www/sokanacademy-php-course/03/03-form/handle_form.php on line 4
Your name is: ;
Your email is: ;
Your gender is: ;
Your age is: 10-20;
Your comment is:

می‌بینیم که در مورد فیلد جنسیت با ارور مواجه شده و الباقی فیلدها هم خالی نمایش داده می‌شوند اما این در حالی است که به سادگی و با استفاده از دستورات شرطی if می‌توان از پر بودن کلیهٔ فیلدها اطمینان حاصل کرد. 

همان‌طور که در فایل HTML فوق مشخص است، فیلد مرتبط با سن کاربر دارای یک مقدار پیش‌فرض (۲۰-۱۰) است و قصد داریم تا در ادامه، آپشنی همچون «لطفاً یک گزینه را انتخاب نمایید» در معرض دید کاربر قرار دهیم. برای این منظور داریم:

<select name="age">
    <option value="default">Please choose an option</option>
    <option value="10-20">10-20</option>
    <option value="20-30">20-30</option>
    <option value="30-40">30-40</option>
    <option value="40-50">40-50</option>
    <option value="50-60">50-60</option>
    <option value="60-70">60-70</option>
    <option value="70-80">70-80</option>
</select>

در حقیقت، آپشنی با مقدار default و عنوان Please choose an option پیش از سایر آپشن‌ها در نظر گرفته‌ایم و این در حالی است که اگر اکنون صفحه را رِفرش کنیم، خواهیم دید که کاربر بایستی روی این فیلد کلیک کرده و یکی از گزینه‌ها را انتخاب نماید. حال برای اطمینان حاصل کردن از پر بودن کلیهٔ‌ فیلدها، ابتدا اسکریپت قرار گرفته داخل فایل handle_form.php را تکمیل کرده سپس به تفسیر آنها خواهیم پرداخت:

<?php
$name = $_REQUEST['name'];
$email = $_REQUEST['email'];
$gender = $_REQUEST['gender'];
$age = $_REQUEST['age'];
$comment = $_REQUEST['comment'];

if (empty($name)) {
    echo "Please fill in the name field <br>";
} else {
    if (empty($email)) {
        echo "Please fill in the email field <br>";
    } else {
        if (! isset($gender)) {
            echo "Please fill in the gender field <br>";
        } else {
            if ($age == 'default') {
                echo "Please fill in the age field <br>";
            } else {
                if (empty($comment)) {
                    echo "Please fill in the comment field <br>";
                } else {
                    echo "Your name is: $name;<br> Your email is: $email;<br> Your gender is: $gender;<br> Your age is: $age;<br> Your comment is: $comment";
                }
            }
        }
    }
}

اکنون یک بار بدون این‌ که هیچ‌کدام از فیلدها را پر کنیم، روی دکمهٔ Submit کلیک می‌کنیم:

Notice: Undefined index: gender in /var/www/sokanacademy-php-course/03/03-form/handle_form.php on line 4
Please fill in the name field

می‌بینیم هشداری دریافت می‌کنیم مبنی بر این که اندیس gender نامعلوم (Undefined) است. برای رفع این مشکل، دو راه‌کار پیش رو داریم؛ راه‌کار اول، استفاده از اپراتور @ است که پیش از این به معرفی آن پرداختیم. در واقع، کاری که این اپراتور انجام می‌دهد این است که جلوی نمایش هشدارها و اخطارهایی که توسط مفسر PHP ایجاد می‌شوند را می‌گیرد (گفتیم که تا حد ممکن از این اپراتور برای چنین کاربرد‌هایی نباید استفاده کرد چرا که در پروژه‌های بزرگ ممکن است فرایند دیباگینگ پروژه را با دردسر مواجه سازد):

$gender = @$_REQUEST['gender'];

از این پس، دیگر تحت هیچ‌ عنوان اخطاری در معرض دید کاربر قرار نخواهد گرفت. به عنوان راه‌کار دوم، می‌توان از یک دستور شرطی استفاده کرد:

if (isset($_REQUEST['gender'])) {
  $gender = $_REQUEST['gender'];
}

گفتیم که فانکشن ()isset چک می‌کند ببیند که آیا یک متغیر Set (مقداردهی) شده است یا خیر؛ اگر اصطلاحاً Set شده بود، مقدار true و در غیر این صورت، مقدار false را باز می‌گرداند. هر کدام از ترفندهای فوق را که استفاده کنیم، پس از کلیک کردن روی دکمهٔ Submit بدون پر کردن هیچ کدام از فیلدها، خروجی به صورت زیر خواهد بود:

Please fill in the name field

حال برسیم به تفسیر دستورات شرطی که پر بودن فیلدهای فرم را چک می‌کنند. در اولین دستور شرطی که در خط هشتم قرار دارد، از فانکشنی تحت عنوان ()empty استفاده کرده‌ایم که به صورت Built-in (از پیش تعریف شده) در هستهٔ زبان PHP نوشته شده است. کاری که متد ()empty انجام می‌دهد این است که چک می‌کند ببیند آیا پارامتر ورودی‌اش خالی است یا خیر؛ اگر خالی بود، مقدار true را باز می‌گرداند و در غیر این صورت، مقدار false اصطلاحاً return خواهد شد.

از آنجا که ما هیچ چیزی در فیلد مربوط به نام وارد نکرده‌ایم، مسلماً این فانکشن مقدار true را باز می‌گرداند و وارد بلوک if می‌شویم و عبارت Please fill in the name field چاپ می‌شود (لازم به ذکر است برای این که تمامی هشدارها در خطوط مجزایی در معرض دید کاربر قرار گیرند، از تگ <br> در پایان هر پیام استفاده کرده‌ایم).

اما اگر کاربر فیلد مربوط به نام را پر کرده‌ باشد، وارد بلوک else اولین دستور if می‌شویم و مجدداً با استفاده از یک بلوک if else دیگر در خط یازدهم، پر/خالی بودن فیلد مربوط به ایمیل را چک کرده‌ایم.

در ارتباط با متغیر gender$، باتوجه به این که این متغیر از جنسی نیست که بتواند پر/خالی باشد (در واقع این فیلد از نوع Radio است)، برای چک کردن آن از فانکشن ()isset به همراه اپراتور ! استفاده کرده‌ایم. به عبارت دیگر، دستور داده‌ایم که اگر این متغیر مقداردهی نشده بود، وارد بلوک مرتبط با if شویم.

در ادامه، به متغیر age$ می‌رسیم. نکته‌ای که در ارتباط با Value (مقدار) این متغیر وجود دارد این است که اگر آن را با تابع ()empty چک کنیم، این تابع همواره مقدار false را نمایش خواهد داد (به عبارت دیگر، همواره نشان خواهد داد که این فیلد مقداردهی شده است). دلیل اینچنین مسئله‌ای این است که ما به عنوان مقدار اولین آپشن این فیلد، استرینگ default را مورد استفاده قرار داده‌ایم.

در چنین مواقعی، بایستی از اپراتور مقایسه‌ای == استفاده کنیم. همان‌طور که ملاحظه می‌شود، در خط هفدهم گفته‌ایم اگر مقدار متغیر age$ برابر با استرینگ default بود، ارور نمایش داده شود و در غیر این صورت، به مرحلهٔ بعد برویم.

در نهایت، پر/خالی بودن متغیر comment$ را هم در خط بیستم چک کرده و اگر کاربر متنی وارد فیلد مربوطه کرده باشد، وارد بلوک else مرتبط خواهیم شد و مقادیر کلیهٔ متغیرها چاپ خواهند شد:

Your name is: Behzad;
Your email is: behzad.moradi@example.com;
Your gender is: male;
Your age is: 30-40;
Your comment is: This is my first comment.

به نظر می‌رسد که با ذکر مثال فوق، با کاربرد دستورات شرطی در ارتباط با چک کردن فیلدهای فرم‌های HTML آشنا شده باشید. آنچه در این مثال حائز اهمیت می‌باشد این است که این اسکریپت یک آسیب‌پذیری جدی دارد. به عبارت دیگر، اگر کاربری پیدا شود و با استفاده از ابزار Inspect Element مرورگر اقدام به تغییر کدهای HTML کرده و مثلاً مقداری همچون oops را برای یکی از فیلدهای مرتبط با جنسیت یا سن در نظر بگیرد چه‌طور؟

<select name="age">
    <option value="oops">Please choose an option</option>
    <option value="10-20">10-20</option>
    <option value="20-30">20-30</option>
    <option value="30-40">30-40</option>
    <option value="40-50">40-50</option>
    <option value="50-60">50-60</option>
    <option value="60-70">60-70</option>
    <option value="70-80">70-80</option>
</select>

می‌بینیم که فرد هکر در اولین آپشن به جای استرینگ default از استرینگی همچون oops استفاده کرده است و اگر کلیهٔ فیلدهای فرم را پر کرده و فیلد مرتبط با سن را دست‌نخوره باقی بگذاریم، فرم اصطلاحاً Valid (معتبر) بوده و اسکریپت ما بدون نمایش دادن هیچ‌ هشداری تا پایان اجرا می‌گردد:

Your name is: Behzad;
Your email is: behzad.moradi@example.com;
Your gender is: male;
Your age is: oops;
Your comment is: This is my first comment.

در واقع، ما در دستور شرطی مرتبط با متغیر age$ صرفاً گفته‌ایم که اگر مقدار این متغیر برابر با استرینگ default بود به کاربر هشدار داده شود (این قضیه برای فیلد مرتبط با مشخص کردن جنسیت هم کاملاً صادق است).

در چنین مواقعی، با استفاده از دستورات شرطی مختلف و همچنین یکسری فانکشن‌های شخصی‌سازی شده حاوی الگوریتم‌هایی به منظور ارسال دیتای صحیح به سمت سرور،‌ می‌توان جلوی این‌گونه رفتارهای کاربران (هکرها) را گرفت. دانلود فایل‌های تمرین

آشنایی با دستور switch در زبان PHP


پیش از این گفتیم که یکی از انواع ساختارهای شرطی در زبان‌های برنامه‌نویسی مختلف، دستور switch است که به نوعی می‌توان آن را جایگزین چندین دستور if elseif در نظر گرفت. به طور کلی، ساختار دستورات سوئیچ در زبان برنامه‌نویسی PHP به صورت زیر است:

<?php
switch (Value) {
    case First value:
        // Code to be executed if Value = First value
        break;
    case Second value:
        // Code to be executed if Value = Second value
        break;
    case Third value:
        // Code to be executed if Value = Third value
        break;
    default:
        // Code to be executed if Value is different from all cases
}

همان‌طور که از ساختار دستور سوئیچ مشخص است، متغیر یا شرطی را داخل پرانتزهای مرتبط با switch قرار داده سپس در چندین case مختلف می‌سنجیم ببینیم که آیا متغیر/شرط ما با کدام‌ یک از کیس‌ها برابری می‌کند و در نهایت اگر با هیچ‌کدام از کیس‌ها هم‌خوانی نداشت، دستورات داخل بلوک default اجرا خواهند شد. برای روشن‌تر شدن نحوهٔ استفاده از دستور سوئیچ، ابتدا مثالی با دستور if می‌آوریم:

<?php
$i = 2;
if ($i == 0) {
    echo "i equals 0";
} elseif ($i == 1) {
    echo "i equals 1";
} elseif ($i == 2) {
    echo "i equals 2";
} else {
  echo "none of them";
}

متغیری تعریف کرده‌ایم تحت عنوان i$ که مقدار اولیهٔ ۲ را هم برایش در نظر گرفته‌ایم. حال با یکسری دستورات if و elseif سنجیده‌ایم که مقدار این متغیر با کدام یک از شروط برابری می‌کند. اکنون می‌خواهیم دستورات شرطی فوق را با switch ریفکتور (بازنویسی) کنیم:

<?php
$i = 2;
switch ($i) {
    case 0:
        echo "i equals 0";
        break;
    case 1:
        echo "i equals 1";
        break;
    case 2:
        echo "i equals 2";
        break;
    default:
      echo "none of them";
}

ابتدا اسکریپت فوق را در مرورگر اجرا کرده، سپس به تفسیر کدهای فوق خواهیم پرداخت:

i equals 2

ابتدا متغیری تعریف کرده‌ایم تحت عنوان i$ و مقدار پیش‌فرض ۲ را هم برایش در نظر گرفته‌ایم؛ سپس این متغیر را به عنوان پارامتر ورودی دستور switch در نظر گرفته‌ایم و از سه کیس مختلف برای چک کردن مقدار این متغیر استفاده کرده‌ایم.

در کیس اول، کلیدواژهٔ case را نوشته، یک فاصله قرار داده و شرط مد نظر را نوشته‌ایم و پس از شرط هم یک علامت : قرار داده‌ایم (لازم به ذکر است که در کیس اول، شرط برابر بودن مقدار متغیر i$ با عدد ۰ است). نکتهعلامت : اصطلاحاً Colon (کالِن) و علامت ; اصطلاحاً Semicolon (سِمی‌کالِن) گفته می‌شود.

به خاطر داشته باشیم که پس از کلیدواژهٔ case، به جای علامت : می‌توان از علامت ; نیز استفاده کرد:

<?php
$i = 2;
switch ($i) {
    case 0;
        echo "i equals 0";
        break;
    case 1;
        echo "i equals 1";
        break;
    case 2;
        echo "i equals 2";
        break;
    default:
      echo "none of them";
}

پس از هر دستور case، بایستی دستوراتی که مد نظرمان هست را بنویسیم. مثلاً چنانچه مقدار متغیر i$ برابر با ۰ باشد، دستور داده‌ایم که با استفاده از echo استرینگ i equals 0 چاپ شود.

نکتهٔ مهمی که در اینجا وجود دارد، استفادهٔ درست از دستور break است. این دستور -همان‌طور که از نامش مشخص است- این وظیفه را دارا است تا روند اجرای برنامه را متوقف سازد. به عبارت دیگر، چنانچه شرط در نظر گرفته شده در اولین case برآورده شود، دستورات قرار گرفته داخل این بلوک اجرا شده سپس دستور break اجرا می‌شود که این وظیفه را دارا است تا ما را از داخل switch خارج ساخته و ادامهٔ برنامه اجرا گردد.

به همین منوال، مقادیر ۱ و ۲ را هم چک می‌کنیم تا در نهایت به دستور default می‌رسیم که کاربردی همچون دستور else در دستورات شرطی if دارد. به عبارت دیگر، چنانچه هیچ‌ کدام از کیس‌ها اصطلاحاً true نباشند، مفسر وارد این بلوک می‌شود (توجه داشته باشید که اگر هر تعداد case پس از default قرار گیرد، هرگز چک نخواهند شد).

پیش از این گفتیم که کاربرد دستور break در سوئیچ‌ها بسیار حائز اهمیت است. برای روشن‌تر شدن این مسئله، کدهای فوق را به صورت زیر تغییر می‌دهیم:

<?php
$i = 0;
switch ($i) {
    case 0:
        echo "i equals 0<br>";
        // break;
    case 1:
        echo "i equals 1<br>";
        // break;
    case 2:
        echo "i equals 2<br>";
        // break;
    default:
      echo "none of them";
}

همان‌طور که می‌بینیم، ابتدا مقدار پیش‌فرض متغیر i$ را برابر با ۰ قرار داده، سپس کلیهٔ دستورات break را کامنت کرده‌ایم (همچنین از تگ <br> برای خواناتر شدن خروجی در داخل استرینگ‌ها استفاده کرده‌ایم). حال اقدام به اجرای این اسکریپت می‌کنیم:

i equals 0
i equals 1
i equals 2
none of them

 می‌بینیم علیرغم اینکه انتظار می‌رود صرفاً case اول اجرا گردد، اما تمامی کیس‌ها و حتی بلوک default نیز اجرا شده است و اینجا است که بایستی به اهمیت کاربرد دستور break پی ببریم. در واقع، کاری که break انجام می‌دهد این است که به محض برآورده شدن شرط، جلوی اجرای ادامهٔ دستورات قرار گرفته داخل سوئیچ را می‌گیرد.

همچنین به خاطر داشته باشیم که به جای دستور break از معادلی همچون continue (که بیشتر در حلقه‌ها استفاده می‌شود) نیز می‌توان استفاده کرد؛ برای مثال:

<?php
$i = 0;
switch ($i) {
    case 0:
        echo "i equals 0";
        continue;
    case 1:
        echo "i equals 1";
        continue;
    case 2:
        echo "i equals 2";
        continue;
    default:
      echo "none of them";
}

خروجی دقیقاً شبیه به زمانی است که از دستور break استفاده کرده بودیم.به خاطر داشته باشیددر دستور سوئیچ، Condition (شرط) فقط یک‌ بار سنجیده می‌شود و نتیجهٔ آن با کیس‌های مختلف مقایسه می‌گردد اما در دستور elseif، شرط هر دفعه سنجیده می‌شود؛ لذا اگر شرط شما کمی پیچیده است و نیاز به منابع سروری دارد، دستور switch در مقایسه با if elseif سریع‌تر است.

نکته‌ای که در ارتباط با سوئیچ در زبان PHP وجود دارد این است که می‌توان مفهوم OR (یا) را نیز در این‌گونه دستورات شرطی پیاده‌سازی کرد:

<?php
$i = 1;
switch ($i) {
    case 0:
    case 1:
    case 2:
        echo "i equals 0 or 1 or 2";
        break;
    default:
      echo "i is less than 0 or greater than 2";
}

به عنوان خروجی اسکریپت فوق داریم:

i equals 0 or 1 or 2

در واقع، چنانچه کیسی را نوشته اما هیچ دستوری برای آن در نظر نگیریم تا در صورت true بودن شرط اجرا گردد، دستور نوشته شدهٔ آخر مبنا قرار داده خواهد شد.

به طور کلی در صورتی که شروط زیاد باشند، دولوپرهای PHP از دستور if استفاده می‌کنند اما اگر اصرار بر استفاده از دستور switch داشته باشید، به شکل زیر خواهید توانست این مدل را پیاده‌سازی کنید:

<?php
$i = 16;
switch ($i) {
    case ($i >= 0 && $i <= 10):
        echo "i is between 0 and 10";
        break;
    case ($i > 10 && $i <= 20):
        echo "i is between 11 and 20";
        break;
    case ($i > 20):
        echo "i is greater than 20";
        break;
    default:
      echo "none of them";
}

به عنوان خروجی داریم:

i is between 11 and 20

اگر هم بخواهیم استرینگ‌ها را در دستور سوئیچ مورد بررسی قرار دهیم، می‌توان به صورت زیر این کار را انجام داد:

<?php
$fruit = 'apple';
switch ($fruit) {
    case 'apple':
        echo "An apple a day, keeps the doctor away!";
        break;
    case 'banana':
        echo "Is kind of delicious.";
        break;
    case 'orange':
        echo "Smells good.";
        break;
    default:
        echo "None of them";
}

به عنوان خروجی داریم:

An apple a day, keeps the doctor away!

حال ببنیم اگر مقدار متغیر fruit$ را برابر با Apple (حرف اول به صورت بزرگ نوشته شده است) قرار دهیم، کدام کیس اجرا می‌شود:

<?php
$fruit = 'Apple';
switch ($fruit) {
    case 'apple':
        echo "An apple a day, keeps the doctor away!";
        break;
    case 'banana':
        echo "Is kind of delicious.";
        break;
    case 'orange':
        echo "Smells good.";
        break;
    default:
        echo "None of them";
}

به عنوان خروجی داریم:

None of them

در واقع، از آنجا که apple و Apple دو استرینگ متمایز هستند، کیس اول هرگز true نخواهد شد و دستور داخل default اجرا می‌گردد. برای رفع این مشکل می‌توان کدهای فوق را به صورت زیر ریفکتور کنیم:

<?php
$fruit = 'Apple';
switch (strtolower($fruit)) {
    case 'apple':
        echo "An apple a day, keeps the doctor away!";
        break;
    case 'banana':
        echo "Is kind of delicious.";
        break;
    case 'orange':
        echo "Smells good.";
        break;
    default:
        echo "None of them";
}

مجدد کدهای فوق را اجرا می‌کنیم:

An apple a day, keeps the doctor away!

می‌بینیم که کیس اول به درستی برابر با true شد. در حقیقت، کاری که فانکشن ()strtolower انجام می‌دهد این است که کلیهٔ حروف بزرگ پارامتر ورودی‌اش را به حروف کوچک تبدیل می‌کند (فانکشن دیگری داریم تحت عنوان ()strtoupper که دقیقاً عکس فانکشن ()strtolower عمل می‌کند؛ به عبارت دیگر، کلیهٔ حروف کوچک پارامتر ورودی‌اش را به حروف بزرگ تبدیل می‌کند).

ساخت ماشین‌ حسابی ساده در زبان PHP با استفاده از دستورات if و switch


به منظور درک ماهیت دستورات شرطی if و switch در زبان PHP، در این آموزش قصد داریم آنچه تاکنون در مورد دستورات شرطی فرا گرفته‌ایم را در قالب یک پروژهٔ ماشین حساب ساده پیاده‌سازی کنیم. برای این منظور، ابتدا کدهای زیر را در نظر می‌گیریم:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Simple PHP Calculator</title>
</head>
<body>
    <form action="index.php" method="POST">
        First number:
        <br>
        <input type="text" name="number1">
        <br>
        Second number:
        <br>
        <input type="text" name="number2">
        <br>
        Operation type:
        <br>
        <input type="radio" name="operation_type" value="+"> +
        <br>
        <input type="radio" name="operation_type" value="-"> -
        <br>
        <input type="radio" name="operation_type" value="*"> ×
        <br>
        <input type="radio" name="operation_type" value="/"> ÷
        <br>
        <input type="submit" name="submit" value="=">
    </form>
    <?php
    $firstNumber = $_REQUEST['number1'];
    $secondNumber = $_REQUEST['number2'];
    $operationType = $_REQUEST['operation_type'];
    $result = null;

    switch ($operationType) {
        case '+':
            $result = $firstNumber + $secondNumber;
            break;
        case '-':
            $result = $firstNumber - $secondNumber;
            break;
        case '*':
            $result = $firstNumber * $secondNumber;
            break;
        case '/':
            $result = $firstNumber / $secondNumber;
            break;
        default:
            $result = "Undefined operation!";
      }
      echo 'Result is <strong style="color:#ffde57">' . $result . '</strong>';
    ?>
</body>
</html>

می‌بینیم که در این پروژه، کدهای HTML و PHP را در قالب یک فایل در کنار یکدیگر قرار داده‌ایم. لذا ضروری است که پسوند فایل مد نظر حتماً php. باشد چرا که در غیر این صورت، اگر فایل را در لوکال‌هاست اجرا کنیم، کدهای PHP تفسیر نخواهند شد. باتوجه به این که کدهای PHP که قرار است معادلات را انجام دهند داخل همین فایل قرار دارند، لذا ضروری است که به عنوان مقدار اتریبیوت action این فرم، نام همین فایل -index.php- را قرار دهیم. به عبارت دیگر، با Submit کردن این فرم، دیتای فرم به همین فایل اجراع داده خواهند شد.

در تفسیر کدهای فوق بایستی بگوییم که یک فرم سادهٔ HTML طراحی کرده‌ایم که حاوی دو فیلد برای گرفتن اعداد و فیلدی هم برای مشخص کردن نوع علمیات ریاضیاتی دارا است. سپس داخل تگ‌های <? php?> که پس از فرم مد نظر قرار گرفته‌اند، چهار متغیر تعریف کرده‌ایم تحت عناوین operationType ،$secondNumber ،$firstNumber$ و result$ که به ترتیب به معنی «عدد اول»،‌ «عدد دوم»، «نوع عملیات» و «نتیجه» هستند.

پیش از این، با متغیر به‌ اصطلاح سوپرگلوبال REQUEST_$ آشنا شده‌ایم؛ کاری که این متغیر از پیش تعریف شده در زبان PHP انجام می‌دهد این است که کلیهٔ دیتای ارسالی به صورت GET یا POST را در خود ذخیره می‌سازد. با این تفاسیر، ما به مقادیر فیلدهای فرم خود دسترسی داشته و آنها را در متغیرهایی متناظر با نام‌شان ذخیره می‌سازیم.

همچنین فیلدی داشتیم از نوع Radio که نوع علمیات ریاضیاتی را مشخص می‌کرد؛ مقدار این فیلد را در متغیر مرتبط با آن ریخته و در نهایت یک متغیر تحت عنوان result$ به منظور ذخیره‌سازی نتیجهٔ نهایی با مقدار پیش‌فرض null ایجاد کرده‌ایم.

همان‌طور که مشاهده می‌شود، در ادامه از یک دستور شرطی switch استفاده کرده‌ایم که متغیر operationType$ را به عنوان پارامتر ورودی گرفته و بسته به مقدار آن، یکی از دستورات مرتبط با چهار عمل اصلی را انجام می‌دهد و چنانچه شرطی برقرار نگردد، دستور داخل default اجرا می‌گردد که چیزی نیست جز اختصاص استرینگی تحت عنوان !Undefined operation به متغیر result$. در نهایت هم استرینگی با کمی کد CSS حاوی مقدار متغیر result$ را چاپ کرده‌ایم. حال برای تست، یک بار از طریق لوکال‌هاست فایل مد نظر را باز می‌کنیم:

Notice: Undefined index: number1 in /var/www/sokanacademy-php-course/03/03-calculator/index.php on line 31

Notice: Undefined index: number2 in /var/www/sokanacademy-php-course/03/03-calculator/index.php on line 32

Notice: Undefined index: operation_type in /var/www/sokanacademy-php-course/03/03-calculator/index.php on line 33
Result is Undefined operation!

می‌بینیم بدون این که کاری انجام دهیم، سه هشدار در معرض دیدمان قرار گرفته‌ است. دلیل چنین مسئله‌ای آن است که به محض اجرای این فایل، مفسر PHP به سراغ کدهایی که مابین تگ‌های <? php?> قرار گرفته می‌رود و از آنجا که هیچ دیتایی از طریق فرم مد نظر اصطلاحاً POST (ارسال) نشده است، مسلماً داخل متغیر سوپرگلوبال REQUEST_$ نیز هیچ‌کدام از کلیدهای در نظر گرفته شده (همچون number1 و غیره) وجود ندارد و لذا مفسر PHP به ما هشدار می‌دهد که چنین کلیدهایی وجود خارجی ندارند! برای رفع این مشکل، کدهای فوق را به صورت زیر ریفکتور می‌کنیم:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Simple PHP Calculator</title>
</head>
<body>
    <form action="index.php" method="POST">
        First number:
        <br>
        <input type="text" name="number1">
        <br>
        Second number:
        <br>
        <input type="text" name="number2">
        <br>
        Operation type:
        <br>
        <input type="radio" name="operation_type" value="+"> +
        <br>
        <input type="radio" name="operation_type" value="-"> -
        <br>
        <input type="radio" name="operation_type" value="*"> ×
        <br>
        <input type="radio" name="operation_type" value="/"> ÷
        <br>
        <input type="submit" name="submit" value="=">
    </form>
    <?php
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $firstNumber = $_REQUEST['number1'];
        $secondNumber = $_REQUEST['number2'];
        $operationType = $_REQUEST['operation_type'];
        $result = null;

        switch ($operationType) {
            case '+':
                $result = $firstNumber + $secondNumber;
                break;
            case '-':
                $result = $firstNumber - $secondNumber;
                break;
            case '*':
                $result = $firstNumber * $secondNumber;
                break;
            case '/':
                $result = $firstNumber / $secondNumber;
                break;
            default:
                $result = "Undefined operation!";
          }
          echo 'Result is <strong style="color:#ffde57">' . $result . '</strong>';
    }
    ?>
</body>
</html>

در حقیقت، کاری که پس از ریفکتور کردن کدهای فوق صورت گرفته این است که کلیهٔ اسکریپت‌های PHP را داخل یک دستور شرطی قرار داده و در این دستور شرطی هم گفته‌ایم چنانچه کلید REQUEST_METHOD متغیر سوپرگلوبال REQUEST_$ برابر با POST بود، دستورات داخل if اجرا شوند و در غیر این صورت،‌ هیچ اتفاقی رخ ندهد. به عبارت دیگر، اسکریپت‌های ما صرفاً زمانی اجرا خواهند شد که کاربر روی دکمهٔ = کلیک کند (یا فرم را اصطلاحاً Submit کند).

اکنون جهت تست برنامه، در فیلد اول عددی همچون ۷ و در فیلد دوم نیز عددی همچون ۳ را وارد کرده سپس یکی از چهار عمل اصلی همچون + را در نظر می‌گیریم و روی دکمهٔ = کلیک می‌کنیم و خواهیم دید که عدد ۱۰ به رنگ زرد نمایش داده خواهد شد. تا اینجای کار برنامه‌ به درستی کار می‌کند اما قصد داریم در ادامه شرایط مختلفی را در نظر بگیریم.

به طور مثال، قصد داریم ببینیم که اگر کاربر سهواً یا عمداً به جای یک عدد صحیح -همچون اعداد ۰ تا ۹- یک حرف یا علامت -همچون A یا #- را وارد فیلد اعداد کند چه اتفاقی رخ خواهد داد؟ با تست شرایط فوق در برنامه، می‌بینیم که نتیجهٔ مد نظر به‌دست نمی‌آید؛ برای این منظور، می‌بایست مجدد کدهای فوق را به‌صورت زیر ریفکتور و تکمیل کنیم:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Simple PHP Calculator</title>
</head>
<body>
    <form action="index.php" method="POST">
        First number:
        <br>
        <input type="text" name="number1">
        <br>
        Second number:
        <br>
        <input type="text" name="number2">
        <br>
        Operation type:
        <br>
        <input type="radio" name="operation_type" value="+"> +
        <br>
        <input type="radio" name="operation_type" value="-"> -
        <br>
        <input type="radio" name="operation_type" value="*"> ×
        <br>
        <input type="radio" name="operation_type" value="/"> ÷
        <br>
        <input type="submit" name="submit" value="=">
    </form>
    <?php
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $firstNumber = $_REQUEST['number1'];
        $secondNumber = $_REQUEST['number2'];
        $operationType = $_REQUEST['operation_type'];
        $result = null;
        if (is_numeric($firstNumber) && is_numeric($secondNumber)) {
            switch ($operationType) {
                case '+':
                $result = $firstNumber + $secondNumber;
                break;
                case '-':
                $result = $firstNumber - $secondNumber;
                break;
                case '*':
                $result = $firstNumber * $secondNumber;
                break;
                case '/':
                $result = $firstNumber / $secondNumber;
                break;
                default:
                $result = "Undefined operation!";
            }
            echo 'Result is <strong style="color:#ffde57">' . $result . '</strong>';
        } else {
            echo 'Please enter a valid value.';
        }
    }
    ?>
</body>
</html>

کاری که در اسکریپت فوق انجام داده‌ایم این است که از یک دستور شرطی if به همراه فانکشن از پیش تعریف شده‌ای در زبان PHP تحت عنوان ()is_numeric جهت تست کردن فیلدها استفاده کرده‌ایم. به عبارت دیگر، فانکشن ()is_numeric چک می‌کند ببیند که آیا مقدار پارامتر ورودی‌اش عدد است یا خیر؛ اگر عدد بود مقدار true و در غیر این صورت مقدار false را باز می‌گرداند. در این دستور شرطی با استفاده از اپراتور && به معنی «و» دستور داده‌ایم که اگر هر دوی متغیرها مقدار عددی داشتند، دستورات داخل if اجرا شده و در غیر این صورت دستور داخل else که حاوی چاپ عبارت .Please enter a valid value است چاپ شود.

آنچه مسلم است اینکه این برنامه به‌مراتب بیشتر جای کار دارد؛ به طور مثال، بایستی اگر کاربری فیلدها را پر کرد اما یکی از اِلِمان‌های Radio را انتخاب نکرد جلویش گرفته شود و یا اگر مثلاً عدد ۰ را تقسیم بر ۸ کرد به وی هشدار داده شود که چنین مسائلی به سادگی با استفاده از چندین دستور شرطی دیگر امکان‌پذیر خواهند شد.  دانلود فایل‌های تمرین

مطالب مرتبط

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *