FA-TOOLS — Header Component

آموزش جامع ساخت فرم چندمرحله‌ای بدون افزونه در وردپرس

خلاصه کاربردی مقاله:

در این مقاله، یک فرم چندمرحله‌ای سبک، فوق‌العاده سریع و اختصاصی را بدون نصب هیچ‌گونه افزونه سنگین وردپرسی می‌سازیم. با ترکیب ساختار استاندارد HTML، استایل‌های مدرن CSS، منطق اعتبارسنجی جاوااسکریپت و سیستم AJAX اختصاصی وردپرس، فرمی خواهید داشت که نرخ تبدیل کاربران را تا بیش از ۳۰ درصد افزایش می‌دهد و سرعت پایگاه داده و سایت شما را حفظ می‌کند.

چرا ساخت فرم چندمرحله‌ای بدون افزونه، انتخاب هوشمندانه‌تری است؟

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

افزونه‌های محبوب فرم‌ساز مانند Gravity Forms یا WPForms فوق‌العاده هستند، اما برای فرم‌های اختصاصی یا سایت‌هایی که سرعت در آن‌ها حرف اول را می‌زند، گزینه‌های ایده‌آلی نیستند. افزونه‌ها اغلب کدهای اضافه، جدول‌های جدید در دیتابیس و اسکریپت‌های بلاک‌کننده رندر ایجاد می‌کنند. با ساخت فرم کدنویسی شده، می‌توانید دقیقاً بر اساس نیاز خود، فیلدها را طراحی کرده و از قطعه کدهای آماده HTML برای ساخت فرم‌های استاندارد استفاده کنید.

روش کدنویسی اختصاصی استفاده از افزونه‌های فرم‌ساز
حجم کد کمتر از ۱۵ کیلوبایت و عدم کاهش سرعت سایت لود چندین فایل خارجی (JS/CSS) با حجم بیش از ۳۰۰ کیلوبایت
شخصی‌سازی ۱۰۰٪ بدون محدودیت در طراحی UI/UX محدود به استایل‌ها و استراکچرهای پیش‌فرض افزونه
امنیت بالا به دلیل عدم وجود آسیب‌پذیری‌های عمومی افزونه‌ها نیازمند آپدیت مداوم جهت جلوگیری از باگ‌های امنیتی
ارسال داده‌ها با AJAX بدون رفرش صفحه و بسیار سریع گاهی نیازمند نسخه پرمیوم برای امکانات سفارشی AJAX

معماری و نحوه کارکرد سیستم

فرم چندمرحله‌ای از چهار لایه اصلی تشکیل شده است: structure (HTML)، ظاهر (CSS)، منطق سمت کلاینت (JS)، و پردازش سمت سرور (PHP). جاوااسکریپت کنترل هدایت کاربر بین مراحل را بدون بارگذاری مجدد صفحه انجام می‌دهد و در گام آخر، اطلاعات را به‌صورت ایمن به Backend وردپرس ارسال می‌کند.

فرایند به این صورت است که تمام مراحل فرم داخل یک تگ “ قرار دارند اما در هر لحظه تنها یک بخش (Step) برای کاربر فعال و قابل مشاهده است. هنگام کلیک روی دکمه «بعدی»، جاوااسکریپت ابتدا ورودی‌های مرحله جاری را اعتبارسنجی کرده و در صورت صحت، بخش فعلی را مخفی و بخش بعدی را نمایان می‌سازد. در نهایت، اطلاعات از طریق مکانیزم `admin-ajax.php` وردپرس همراه با کد امنیتی (Nonce) پردازش می‌شوند.

گام اول: ساختار HTML فرم و نوار پیشرفت

ساختار HTML باید شامل نوار پیشرفت (Progress Bar)، بخش‌های مجزای فرم (Form Steps) و دکمه‌های ناوبری باشد. کد زیر شالوده اصلی فرم سه مرحله‌ای ما را تشکیل می‌دهد. می‌توانید این کد را در یک برگه وردپرس (ویرایشگر HTML) یا فایل قالب خود قرار دهید.

<!-- Multi Step Form Wrapper -->
<div class="custom-multi-step-form">
    
    <!-- Progress Bar -->
    <div class="form-progress">
        <div class="progress-step active" data-step="1"><span>۱</span>اطلاعات فردی</div>
        <div class="progress-step" data-step="2"><span>۲</span>اطلاعات تماس</div>
        <div class="progress-step" data-step="3"><span>۳</span>توضیحات نهایی</div>
    </div>

    <form id="wp-custom-form" method="post">
        
        <!-- Step 1 -->
        <div class="form-step step-1 active">
            <h3 style="text-align:right;">گام اول: اطلاعات فردی</h3>
            <div class="form-field">
                <label for="user_fname">نام و نام خانوادگی:</label>
                <input type="text" id="user_fname" name="user_fname" required>
            </div>
            <div class="form-buttons">
                <button type="button" class="btn btn-next">مرحله بعدی &laquo;</button>
            </div>
        </div>

        <!-- Step 2 -->
        <div class="form-step step-2" style="display:none;">
            <h3 style="text-align:right;">گام دوم: اطلاعات تماس</h3>
            <div class="form-field">
                <label for="user_email">پست الکترونیک:</label>
                <input type="email" id="user_email" name="user_email" required>
            </div>
            <div class="form-field">
                <label for="user_phone">شماره همراه:</label>
                <input type="tel" id="user_phone" name="user_phone" required>
            </div>
            <div class="form-buttons">
                <button type="button" class="btn btn-prev">&raquo; مرحله قبلی</button>
                <button type="button" class="btn btn-next">مرحله بعدی &laquo;</button>
            </div>
        </div>

        <!-- Step 3 -->
        <div class="form-step step-3" style="display:none;">
            <h3 style="text-align:right;">گام سوم: توضیحات و ارسال</h3>
            <div class="form-field">
                <label for="user_message">پیام یا درخواست شما:</label>
                <textarea id="user_message" name="user_message" rows="4"></textarea>
            </div>
            <div class="form-buttons">
                <button type="button" class="btn btn-prev">&raquo; مرحله قبلی</button>
                <button type="submit" class="btn btn-submit">ثبت و ارسال فرم</button>
            </div>
        </div>

        <div id="form-response-message" style="margin-top:15px;"></div>
    </form>
</div>

گام دوم: استایل‌دهی CSS و واکنش‌گرایی

برای تجربه کاربری بهتر، استایل‌ها باید تمیز، مدرن و کاملاً مناسب با نمایشگرهای موبایل باشند. اگر نیازمند ایده‌های بیشتر در طراحی UI هستید، می‌توانید از مجموعه تکه‌کدهای CSS کاربردی استفاده کنید. کد CSS زیر را در بخش «سفارشی‌سازی > CSS اضافی» یا فایل `style.css` قالب خود اضافه کنید:

.custom-multi-step-form {
    max-width: 650px;
    margin: 20px auto;
    background: #ffffff;
    border: 1px solid #e2e8f0;
    border-radius: 12px;
    padding: 24px;
    direction: rtl;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.form-progress {
    display: flex;
    justify-content: space-between;
    margin-bottom: 30px;
    position: relative;
}

.progress-step {
    flex: 1;
    text-align: center;
    font-size: 0.85rem;
    color: #64748b;
    font-weight: bold;
    position: relative;
}

.progress-step span {
    display: block;
    width: 32px;
    height: 32px;
    line-height: 32px;
    background: #e2e8f0;
    color: #475569;
    border-radius: 50%;
    margin: 0 auto 8px auto;
    transition: all 0.3s ease;
}

.progress-step.active {
    color: #2563eb;
}

.progress-step.active span {
    background: #2563eb;
    color: #ffffff;
}

.form-field {
    margin-bottom: 18px;
    text-align: right;
}

.form-field label {
    display: block;
    margin-bottom: 6px;
    color: #1e293b;
    font-weight: 600;
    font-size: 0.9rem;
}

.form-field input, .form-field textarea {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid #cbd5e1;
    border-radius: 6px;
    font-size: 0.95rem;
    box-sizing: border-box;
    outline: none;
    transition: border-color 0.2s;
}

.form-field input:focus, .form-field textarea:focus {
    border-color: #2563eb;
}

.form-buttons {
    display: flex;
    justify-content: space-between;
    margin-top: 24px;
}

.btn {
    padding: 10px 20px;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: bold;
    transition: background 0.2s;
}

.btn-next, .btn-submit {
    background: #2563eb;
    color: #ffffff;
    margin-right: auto;
}

.btn-next:hover, .btn-submit:hover {
    background: #1d4ed8;
}

.btn-prev {
    background: #94a3b8;
    color: #ffffff;
}

.btn-prev:hover {
    background: #64748b;
}

.field-error {
    border-color: #ef4444 !important;
}

گام سوم: تعاملات جاوااسکریپت و اعتبارسنجی

ساخت فرم چندمرحله‌ای بدون افزونه در وردپرس — تصویر 5

وظیفه جاوااسکریپت در این فرم، پیمایش بین مراحل و بررسی پر بودن فیلدهای اجباری قبل از عبور به مرحله بعد است. اسکریپت زیر مانع از پیشروی کاربر در صورت خالی بودن ورودی‌های ضروری می‌شود. برای دسترسی به اسکریپت‌های بیشتر، بخش کدهای جاوا اسکریپت را بررسی کنید.

document.addEventListener('DOMContentLoaded', function() {
    const form = document.getElementById('wp-custom-form');
    const steps = Array.from(form.querySelectorAll('.form-step'));
    const progressSteps = document.querySelectorAll('.progress-step');
    let currentStep = 0;

    // Next Step Logic
    form.addEventListener('click', function(e) {
        if (e.target.classList.contains('btn-next')) {
            if (validateStep(currentStep)) {
                steps[currentStep].style.display = 'none';
                currentStep++;
                steps[currentStep].style.display = 'block';
                updateProgress();
            }
        } else if (e.target.classList.contains('btn-prev')) {
            steps[currentStep].style.display = 'none';
            currentStep--;
            steps[currentStep].style.display = 'block';
            updateProgress();
        }
    });

    // Simple Client-side Validation
    function validateStep(stepIndex) {
        let valid = true;
        const inputs = steps[stepIndex].querySelectorAll('input[required], textarea[required]');
        
        inputs.forEach(input => {
            if (!input.value.trim()) {
                valid = false;
                input.classList.add('field-error');
            } else {
                input.classList.remove('field-error');
            }
        });
        return valid;
    }

    // Update Progress Bar
    function updateProgress() {
        progressSteps.forEach((step, idx) => {
            if (idx  res.json())
        .then(data => {
            if(data.success) {
                responseMsg.innerHTML = `<div style="color:#15803d; background:#f0fdf4; padding:10px; border-radius:6px;">${data.data}</div>`;
                form.reset();
                steps[currentStep].style.display = 'none';
                currentStep = 0;
                steps[0].style.display = 'block';
                updateProgress();
            } else {
                responseMsg.innerHTML = `<div style="color:#b91c1c; background:#fef2f2; padding:10px; border-radius:6px;">${data.data}</div>`;
            }
        })
        .catch(err => {
            responseMsg.innerHTML = '<div style="color:#b91c1c;">خطایی در ارسال رخ داد. مجدداً تلاش کنید.</div>';
        })
        .finally(() => {
            submitBtn.disabled = false;
            submitBtn.innerText = 'ثبت و ارسال فرم';
        });
    });
});

گام چهارم: پردازش ایمن داده‌ها در وردپرس (PHP و AJAX)

برای اینکه جاوااسکریپت بتواند با وردپرس ارتباط برقرار کند، باید اکشن‌های AJAX و متغیرهای امنیتی را در PHP تعریف کنیم. این کد داده‌ها را تمیزسازی (Sanitize) کرده و ایمیلی به مدیر سایت ارسال می‌کند.

کد زیر را در فایل `functions.php` پوسته فعال یا افزونه اختصاصی سایت بگذارید. در صورت نیاز به افزودن قابلیت‌های بیشتر به قالب، سری به توابع و تکه‌کدهای وردپرس بزنید.

// Localize Script and Enqueue Variables
function enqueue_multi_step_form_scripts() {
    wp_enqueue_script('jquery'); // Optional, but useful if theme relies on it
    
    // Inject JS variables for AJAX URL and Nonce Security
    wp_register_script('custom-form-script', false);
    wp_enqueue_script('custom-form-script');
    
    wp_localize_script('custom-form-script', 'wp_form_obj', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('msf_security_nonce')
    ));
}
add_action('wp_enqueue_scripts', 'enqueue_multi_step_form_scripts');

// Process Submission via AJAX
function handle_multi_step_form_submission() {
    // 1. Check Nonce Security
    if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'msf_security_nonce')) {
        wp_send_json_error('درخواست نامعتبر و غیرمجاز است.');
    }

    // 2. Sanitize Fields
    $fname   = isset($_POST['user_fname']) ? sanitize_text_field($_POST['user_fname']) : '';
    $email   = isset($_POST['user_email']) ? sanitize_email($_POST['user_email']) : '';
    $phone   = isset($_POST['user_phone']) ? sanitize_text_field($_POST['user_phone']) : '';
    $message = isset($_POST['user_message']) ? sanitize_textarea_field($_POST['user_message']) : '';

    // 3. Validation
    if (empty($fname) || empty($email) || !is_email($email)) {
        wp_send_json_error('لطفاً تمامی فیلدهای الزامی را به‌درستی وارد کنید.');
    }

    // 4. Send Email Notification
    $to      = get_option('admin_email');
    $subject = 'دریافت فرم جدید از سایت: ' . $fname;
    $body    = "اطلاعات فرم ارسال شده:nn";
    $body   .= "نام: $fnamen";
    $body   .= "ایمیل: $emailn";
    $body   .= "تلفن: $phonen";
    $body   .= "پیام:n$messagen";
    $headers = array('Content-Type: text/plain; charset=UTF-8', 'From: ' . get_bloginfo('name') . ' ');

    $sent = wp_mail($to, $subject, $body, $headers);

    if ($sent) {
        wp_send_json_success('اطلاعات شما با موفقیت ثبت و ارسال شد. متشکریم!');
    } else {
        wp_send_json_error('خطا در ارسال ایمیل. لطفاً بعداً دوباره امتحان کنید.');
    }
}
add_action('wp_ajax_submit_custom_multi_step_form', 'handle_multi_step_form_submission');
add_action('wp_ajax_nopriv_submit_custom_multi_step_form', 'handle_multi_step_form_submission');

نکات تخصصی و تجربیات عملی که کمتر جایی می‌بینید

  • ذخیره‌سازی پیش‌نویس در LocalStorage: اگر فرم طولانی است، ورودی‌های کاربر را هنگام تایپ در `localStorage` مرورگر ذخیره کنید. در این صورت اگر کاربر به‌طور اتفاقی صفحه را رفرش کرد، اطلاعات وارد شده پاک نخواهند شد.
  • مقابله با اسپم بدون Captcha (تکنیک Honeypot): یک فیلد مخفی با CSS به فرم اضافه کنید (`display:none`). ربات‌های اسپمر معمولاً تمام فیلدها را پر می‌کنند. در PHP بررسی کنید که اگر این فیلد مخفی پر شده بود، پردازش بدون نمایش خطا متوقف شود.
  • دسترسی‌پذیری (Accessibility – a11y): حتماً از ویژگی‌های `aria-selected` و تغییر فوکوس مرورگر به بالای فرم در زمان رفتن به گام بعدی استفاده کنید تا کاربران کم‌بینا یا کسانی که از کیبورد استفاده می‌کنند دچار سردرگمی نشوند.

عیب‌یابی سریع مشکلات رایج

۱. دکمه مرحله بعدی کار نمی‌کند یا خطا در کنسول نمایش داده می‌شود

علت: عدم بارگذاری جاوااسکریپت یا تداخل با کدهای jQuery پوسته.
راه‌حل: کنسول مرورگر (F12) را چک کنید. مطمئن شوید کدهای JS حتماً بعد از رندر کامل عناصر DOM (رویداد `DOMContentLoaded`) اجرا می‌شوند.

۲. خطای ۴۰۰ یا ۵۰۰ هنگام ارسال فرم (AJAX Failure)

علت: نام اشتباه اکشن در AJAX یا عدم تطابق Nonce امنیتی.
راه‌حل: بررسی کنید نام اکشن ارسال شده در JS (`submit_custom_multi_step_form`) دقیقاً مشابه اسم اکشن ثبت‌شده در توابع `add_action` در PHP باشد.

۳. ایمیل‌های فرم ارسال نمی‌شوند

علت: غیرفعال بودن تابع `mail()` روی سرور یا عدم تنظیم SMTP.
راه‌حل: از افزونه‌های مدیریت SMTP مانند WP Mail SMTP استفاده کنید تا ارسال ایمیل از پروتکل‌های معتبر انجام شود.

پرسش‌های متداول

آیا داده‌های این فرم در دیتابیس وردپرس ذخیره می‌شوند؟

در کد بالا، اطلاعات مستقیماً به ایمیل شما ارسال می‌شوند. اما می‌توانید با تابع `wp_insert_post` یا کدهای SQL سفارشی، داده‌ها را در یک پست تایپ اختصاصی یا جدول مجزا در دیتابیس ذخیره کنید.

آیا این فرم با تمام پوسته‌های وردپرس سازگار است؟

بله، این ساختار به‌صورت استاندارد و مستقل از پلاتفرم ساخته شده و با تمامی پوسته‌ها (شامل المنتور، آسترا، ژنریت‌پرس و…) سازگاری کامل دارد.

چگونه فیلد آپلود فایل را به این فرم چندمرحله‌ای اضافه کنم؟

کافیست تگ “ را اضافه کنید و در فایل PHP با استفاده از تابع `media_handle_upload` وردپرس، فایل‌های دریافتی را پردازش کنید.

چرا از `fetch` به جای `jQuery.ajax` استفاده شده است؟

API استاندارد `fetch` مدرن‌تر است، نیاز به کتابخانه خارجی ندارد و کارایی بهتری در مرورگرهای جدید ایفا می‌کند.

برای دسترسی به مجموعه‌ای از کدهای آماده و بهینه‌سازی شده برای توسعه وردپرس و وب، حتماً از آرشیو کامل قطعه کدهای برنامه‌نویسی دیدن کنید.

Table of Contents

آخرین نوشته‌ها

دیدگاهتان را بنویسید

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