سطح C: فرم‌های هوشمند (Self-Processing Forms)

تا اینجا، ما همیشه دو فایل داشتیم: یک فایل HTML برای فرم و یک فایل PHP برای پردازش. این کار کاملاً درست است، اما در پروژه‌های واقعی، ما اغلب ترجیح می‌دهیم که منطق نمایش فرم و پردازش آن، هر دو در یک فایل باشند. به این الگو «فرم خودپردازش» یا «Self-Processing Form» گفته می‌شود.

محتوای آموزشی

۱. منطق فرم خودپردازش

ایده ساده است. ما یک فایل .php (مثلاً smart_form.php) می‌سازیم که هم کدهای HTML فرم را دارد و هم کدهای PHP پردازش را. منطق برنامه به این صورت خواهد بود:

  1. کاربر فایل smart_form.php را در مرورگر باز می‌کند.
  2. اسکریپت PHP در بالا اجرا می‌شود و «بررسی می‌کند» که آیا فرم ارسال شده یا نه.
  3. اگر بار اول است (فرم ارسال نشده): بخش PHP کاری نمی‌کند و فقط HTML فرم نمایش داده می‌شود.
  4. اگر کاربر فرم را پر کرده و ارسال کرده باشد: صفحه دوباره بارگذاری می‌شود، اما این بار بخش PHP متوجه ارسال فرم شده، داده‌ها را پردازش می‌کند و نتیجه را (معمولاً بالای همان فرم) نمایش می‌دهد.

۲. ابزارها: سوپرگلوبال $_SERVER

برای پیاده‌سازی این منطق، به سوپرگلوبال $_SERVER نیاز داریم. این متغیر یک آرایه غول‌پیکر پر از اطلاعات در مورد سرور و درخواست فعلی کاربر است. ما به دو کلید آن نیاز داریم:

۳. تله امنیتی: htmlspecialchars()

استفاده مستقیم از $_SERVER['PHP_SELF'] در action می‌تواند خطرناک باشد. این یک حفره امنیتی به نام (XSS (Cross-Site Scripting ایجاد می‌کند. (در گام‌های بعدی مفصل به امنیت می‌پردازیم).

قانون: همیشه و همه‌جا، هرگاه خواستید متغیری را در HTML (مخصوصاً در ویژگی‌هایی مثل action یا value) چاپ کنید، باید آن را از تابع htmlspecialchars() عبور دهید. این تابع کاراکترهای خطرناک (مثل < و >) را به موجودیت‌های HTML بی‌خطر (مثل &lt; و &gt;) تبدیل می‌کند.

شکل صحیح: <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" ...>

۴. هشدار: از $_REQUEST دوری کنید!

PHP یک سوپرگلوبال دیگر به نام $_REQUEST هم دارد که به طور وسوسه‌انگیزی، ترکیبی از $_GET، $_POST و $_COOKIE است. استفاده از آن راحت به نظر می‌رسد، اما بسیار بد است. چرا؟ چون شما کنترل خود را بر «منبع» داده از دست می‌دهید. آیا این داده از URL آمده یا از بدنه فرم؟ این ابهام، کدهای شما را ناامن و غیرقابل پیش‌بینی می‌کند.

قانون حرفه‌ای: هرگز از $_REQUEST استفاده نکنید. همیشه صریح باشید: اگر منتظر داده GET هستید، از $_GET استفاده کنید و اگر منتظر POST هستید، از $_POST.


کارگاه عملی: فرم خودپردازش خوش‌آمدگویی

حالا فقط یک فایل به نام self_welcome.php می‌سازیم.

<?php
// ۱. یک متغیر برای پیام خروجی تعریف می‌کنیم
$message = "";

// ۲. بررسی می‌کنیم که آیا متد ارسال، POST بوده است یا نه
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    
    // (از چالش سطح A استفاده می‌کنیم)
    // ۳. بررسی می‌کنیم که آیا داده‌ای ارسال شده یا نه
    if (!empty($_POST['user_name'])) {
        // ۴. داده را پردازش و پیام را آماده می‌کنیم
        // (اینجا هم از htmlspecialchars برای امنیت خروجی استفاده می‌کنیم)
        $name = htmlspecialchars($_POST['user_name']);
        $message = "<div class='alert alert-success'>سلام، " . $name . "! خوش آمدی.</div>";
    } else {
        $message = "<div class='alert alert-danger'>لطفاً نام خود را وارد کنید.</div>";
    }
}
// اگر متد POST نباشد (یعنی GET باشد)، بلوک if اجرا نمی‌شود و $message خالی می‌ماند.
?>

<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
    <meta charset="UTF-8">
    <title>فرم خودپردازش</title>
    <!-- (لینک‌های CSS باید اینجا باشند) -->
</head>
<body>
    <div class="container">
        <h2>فرم خودپردازش</h2>

        <!-- ۵. نمایش پیام (فقط اگر چیزی در آن باشد) -->
        <?php echo $message; ?>

        <!-- ۶. فرمی که به خودش ارسال می‌کند -->
        <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="POST">
            <label for="fname">نام شما:</label>
            <input type="text" id="fname" name="user_name">
            <input type="submit" value="ارسال">
        </form>
    </div>
</body>
</html>

خروجی و تحلیل:

حالت ۱ (بار اول): وقتی self_welcome.php را باز می‌کنید، REQUEST_METHOD برابر GET است. if اجرا نمی‌شود، $message خالی است. فقط فرم خالی نمایش داده می‌شود.

حالت ۲ (پس از ارسال): نام «علی» را وارد و ارسال می‌کنید. صفحه رفرش می‌شود. این بار REQUEST_METHOD برابر POST است. if اجرا می‌شود، $_POST['user_name'] خوانده شده و $message پر می‌شود. سپس در HTML، هم $message (پیام سبز) و هم فرم، دوباره نمایش داده می‌شوند.


تمرین شما

صورت تمرین: ارتقای ماشین حساب

ماشین حساب سطح B خود را به یک فایل خودپردازش به نام smart_calc.php ارتقا دهید.

  1. کل کد باید در یک فایل باشد.
  2. فرم باید با متد POST به htmlspecialchars($_SERVER['PHP_SELF']) ارسال شود.
  3. در بالای فایل، باید با if ($_SERVER['REQUEST_METHOD'] == 'POST') بررسی کنید که آیا فرم ارسال شده است.
  4. اگر فرم ارسال شده بود، باید (با استفاده از isset() یا !empty()) بررسی کنید که هر دو فیلد num1 و num2 وجود دارند و خالی نیستند.
  5. اگر وجود داشتند، جمع را محاسبه کرده و در متغیری (مثلاً $result) ذخیره کنید.
  6. در بخش HTML، باید یک if بگذارید که اگر $result محاسبه شده بود (یعنی isset($result))، آن را در یک h3 نمایش دهد. (مثلاً: <h3>نتیجه: <?php echo $result; ?></h3>)

باشگاه ذهن: فرم‌های چسبنده (Sticky Forms)

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

به فرم‌هایی که مقادیر ارسال شده قبلی را «به خاطر می‌آورند» و در فیلدها نمایش می‌دهند، «فرم چسبنده» (Sticky Form) می‌گویند.

وظیفه: یک پرامپت برای هوش مصنوعی بنویسید و از او بخواهید:

  1. توضیح دهد که «فرم چسبنده» (Sticky Form) چیست؟
  2. چگونه می‌توان با استفاده از PHP، مقدار ارسال شده در $_POST را در ویژگی value یک تگ <input> چاپ کرد؟ (مثال: <input type="text" name="user_name" value="...">)
  3. از او بخواهید کد «کارگاه عملی» (self_welcome.php) را طوری تغییر دهد که «چسبنده» باشد. یعنی اگر کاربر نام «علی» را ارسال کرد، پس از رفرش صفحه، کلمه «علی» همچنان داخل کادر متنی باقی بماند. (راهنمایی: این کار به isset() در داخل تگ value نیاز دارد تا در بار اول خطا ندهد).