آموزش ساخت پنل تنظیمات در وردپرس بدون Settings API

در اکثر قالب های وردپرس صفحه یا صفحاتی به نام پنل تنظیمات وجود دارد که برای سفارشی سازی بخش های مختلف قالب استفاده می شود، این پنل باعث خواهد شد کاربران به جای آنکه مستقیما فایل های PHP و CSS قالب را تغییر دهند، از طریق مجموعه ای از آپشن ها که توسعه دهنده قالب فراهم کرده است نیاز خود را مرتفع کنند.

البته این موضوع بستگی به قالب دارد که تا چه اندازه امکانات و قابلیت های مختلفی برای کاربرانش فراهم کرده باشد. با این حال چگونه می توانیم در پنل مدیریتی وردپرس یک صفحه تنظیمات(Settings Page) ایجاد کنیم؟

دو روش مرسوم برای اینکار وجود دارد:

  • روش پیشنهادی و البته رسمی وردپرس، یعنی Settings API
  • استفاده از فریمورک های قدرتمندی مثل Titan یا Redux

البته ما در این آموزش از روش های بالا استفاده نخواهیم کرد، با توجه به اینکه وردپرس Settings API را در اختیارمان قرار داده است اما ترجیح می دهیم ساختارشکنی کرده و درگیر پیچیدگی های آن نشویم.

بسیار خب، برای اینکه بدانید در انتهای این آموزش به چه چیزی خواهید رسید به تصویر زیر دقت کنید.

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

ایجاد پنل تنظیمات وردپرس بدون settings API

 

قبل از آنکه وارد مباحث پیاده سازی شویم ابتدا دایرکتوری و فایل های زیر را در قالب وب سایت تان ایجاد کنید:

  1. دایرکتوری theme-settings
  2. فایل options-panel.php
  3. فایل options-panel-template.php

ساختار قالب صفحه تنظیمات وردپرس

 

حالا باید فایل options-panel.php را به وردپرس معرفی کنید، پس کد زیر را در ابتدای فایل functions.php قرار دهید.

require get_template_directory() . '/theme-settings/options-panel.php';

 

بسیار خب، در ادامه مراحل زیر را به ترتیب انجام دهید:

گام ۱- ایجاد صفحه تنظیمات در پنل مدیریتی وردپرس

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

add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );

 

هر پارامتر را به سرعت توضیح می دهیم:

  1. page_title$ (الزامی): عنوان صفحه تنظیمات، مقدار این پارامتر در تگ <title> صفحه تنظیمات قرار می گیرد.
  2. menu_title$ (الزامی): عنوان منو
  3. capability$ (الزامی): چه نقش یا مجوزهایی می توانند به این صفحه دسترسی داشته باشند.
  4. menu_slug$ (الزامی): نام یکتایی که در URL صفحه تنظیمات استفاده می شود.
  5. function$ (الزامی) : قالب HTML و آپشن های صفحه تنظیمات توسط این پارامتر ایجاد خواهد شد.
  6. icon_url$ (اختیاری): آیکون منو. برای اطلاعات بیشتر مطلب چگونه از فونت آیکون های وردپرس(Dashicons) استفاده کنیم؟ را مطالعه فرمائید.
  7. position$ (اختیاری): یک عدد صحیح که مشخص می کند صفحه تنظیمات چه جایگاهی در بین سایر منوها داشته باشد، مثلا عدد ۶۲ صفحه تنظیمات را بعد از منوی نمایش قرار می دهد.

حالا کدهای زیر را به فایل options-panel.php اضافه کنید.

function modiredev_add_settings_page()
{
    add_menu_page(
        'تنظیمات قالب',
        'تنظیمات قالب',
        'manage_options',
        'panel-settings',
        'modiredev_render_settings_panel',
        'dashicons-admin-customizer',
        ۶۲
    );
}

add_action( 'admin_menu', 'modiredev_add_settings_page' );

 

تغییرات را ذخیره کرده و وارد پنل مدیریتی وردپرس شوید، همانطور که ملاحظه می کنید پس از منوی نمایش منوی “تنظیمات قالب” اضافه شده است، اگر روی منو کلیک کنید یک خطا صادر می شود، چون هنوز تابع modiredev_render_settings_panel را ایجاد نکردیم، تابع فوق را در گام سوم ایجاد می کنیم.

گام ۲- فرم تنظیمات قالب

در این مرحله فیلدهای موردنیاز تنظیمات را ایجاد می کنیم، کدهای زیر را در فایل options-panel-template.php قرار دهید.

<?php
if ( !empty( $message) ) {
    ?>
    <div class="notice notice-success">
        <p><?php echo $message; ?></p>
    </div>
    <?php
}
?>
<div class="wrap">
    <div id="icon-edit" class="icon2 icon-32-posts-post"></div>
    <h2>پروفایل شبکه های اجتماعی</h2>
    <form action="" method="post">
        <?php wp_nonce_field( 'md_settings_nonce_action', 'md_settings_nonce' ) ?>
        <table class="form-table">
            <tbody>
            <tr>
                <th scope="row">
                    <label for="twitter_url">توئیتر (Twitter):</label>
                </th>
                <td>
                    <input type="text"
                           id="twitter_url"
                           name="panel_settings[twitter_url]"
                           value="<?php echo esc_attr( ( isset( $panel_settings_saved['twitter_url'] ) ?
                               $panel_settings_saved['twitter_url'] : '' ) ); ?>"
                           aria-required="true"
                           class="regular-text">
                </td>
            </tr>
            <tr>
                <th scope="row">
                    <label for="facebook_url">فیسبوک (Facebook):</label>
                </th>
                <td>
                    <input type="text"
                           id="facebook_url"
                           name="panel_settings[facebook_url]"
                           value="<?php echo esc_attr( ( isset( $panel_settings_saved['facebook_url'] ) ?
                               $panel_settings_saved['facebook_url'] : '' ) ); ?>"
                           aria-required="true"
                           class="regular-text">
                </td>
            </tr>
            <tr>
                <th scope="row">
                    <label for="instagram_url">اینستاگرام (Instagram):</label>
                </th>
                <td>
                    <input type="text"
                           id="instagram_url"
                           name="panel_settings[instagram_url]"
                           value="<?php echo esc_attr( ( isset( $panel_settings_saved['instagram_url'] ) ?
                               $panel_settings_saved['instagram_url'] : '' ) ); ?>"
                           aria-required="true"
                           class="regular-text">
                </td>
            </tr>
            </tbody>
        </table>
        
        <hr>
        <h2>سایر تنظیمات</h2>
        
        <table class="form-table">
            <tbody>
            <tr>
                <th scope="row">
                    <label for="email_url">آدرس ایمیل وب سایت:</label>
                </th>
                <td>
                    <input type="text"
                           id="email_url"
                           name="panel_settings[email_url]"
                           value="<?php echo esc_attr( ( isset( $panel_settings_saved['email_url'] ) ?
                               $panel_settings_saved['email_url'] : '' ) ); ?>"
                           aria-required="true"
                           class="regular-text">
                </td>
            </tr>
            </tbody>
        </table>
        <p class="submit">
            <input type="submit" name="md_settings_save" class="button button-primary"
                   value="ذخیره">
        </p>
    </form>
</div>

 

  1. از تابع wp_nonce_field برای ایجاد رشته نانس استفاده کردیم، این رشته در گام سوم اعتبارسنجی می شود تا مطمئن شویم داده ها از منبع معتبری ارسال شده است، در صورتی که با نانس آشنایی ندارید حتما مقاله امنیت وردپرس: نانس(Nonce) دیواری محکم در مقابل حملات CSRF را مطالعه فرمائید.
  2. اگر به خصوصیت name فیلدهای input دقت کنیم از مقدار panel_settings در نامگذاری آنها استفاده شده است، چون می خواهیم مقادیر وارد شده کاربران را به صورت آرایه ای در گام سوم دریافت کرده و مستقیما در دیتابیس ذخیره کنیم.
  3. همانطور که ملاحظه می کنید در ویژگی value فیلدهای input مقدار متغیر panel_settings_saved$ را بررسی کردیم، مقدار این متغیر در گام سوم از دیتابیس فراخوانی و در این متغیر قرار می گیرد.
  4. در نهایت وقتی کاربر روی دکمه “ذخیره” کلیک می کند مقادیر وارد شده در گام سوم از طریق متغیر سراسری post_$ قابل دسترس خواهد بود.

گام ۳- نمایش فرم تنظیمات قالب

پارامتر پنجم تابع ()add_menu_page از نوع Callback است، یعنی وردپرس پس از افزودن منو آن را به سرعت اجرا خواهد کرد. بنابراین برای رفع خطای گام اول کدهای زیر را به انتهای فایل options-panel.php اضافه کنید.

function modiredev_render_settings_panel()
{

    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( 'کاربر غیرمجاز است' );
    }

    if ( isset( $_POST['md_settings_save'] ) ) {

        foreach ( $_POST['panel_settings'] as $key => $value ) {
            $_POST[$key] = sanitize_text_field( $value );
        }

        if ( isset( $_POST['panel_settings'] ) && isset( $_POST['md_settings_nonce'] ) ) {
            if ( !wp_verify_nonce( $_POST['md_settings_nonce'], 'md_settings_nonce_action') ) {
                wp_die( 'نانس مورد تایید نیست' );
            }
            update_option( 'modiredev_panel_settings', $_POST['panel_settings'], 'yes' );
            $message = 'تنظیمات ذخیره شد';
        }
    }

    $panel_settings_saved = get_option( 'modiredev_panel_settings' );
    include 'options-panel-template.php';
}

 

  1. با تابع current_user_can دسترسی های غیرمجاز را بررسی کردیم(محض احتیاط)، اگر کاربر جاری مجوزهای مدیریتی را نداشته باشد ادامه کدها اجرا نخواهد شد و طبیعتا تنظیمات هم در دیتابیس ذخیره نمی شود.
  2. در خط بعد با بررسی مقدار md_settings_save مطمئن شدیم که کاربر بر روی دکمه “ذخیره” کلیک کرده است.
  3. با تابع sanitize_text_field داده های ارسالی را از موارد مشکوک پاکسازی کردیم.
  4. تابع wp_verify_nonce رشته نانس را اعتبارسنجی می کند.
  5. تنظیمات را با تابع update_option در دیتابیس وردپرس ذخیره می کنیم، پارامتر سوم این تابع با yes مقداردهی شده است، یعنی تنظیمات فوق به صورت خودکار در کلیه صفحات لود خواهد شد، برای اطلاعات بیشتر مطلب آموزشی بهبود عملکرد وردپرس با پاکسازی جدول wp_options و داده های Autoloaded را مطالعه فرمائید.
  6. تابع get_option تنظیمات را از دیتابیس دریافت و در متغیر panel_settings_saved$ قرار می دهد.
  7. تابع include هم صفحه تنظیمات قالب را بارگذاری می کند.

 

کار ما با پنل مدیریتی تمام شد، هم اکنون تنظیمات قالب در جدول wp_options ذخیره شده است، ()update_options و ()get_options توابعی هستند که با این جدول سر و کار دارند.

برای اینکه ببینید این داده ها چگونه در دیتابیس وردپرس ذخیره شده است کوئری زیر را از طریق phpMyAdmin اجرا کنید.

SELECT * FROM wp_options WHERE option_name = 'modiredev_panel_settings'

 

همانطور که ملاحظه می کنید هر چهار فیلد فقط در یک رکورد جدول ذخیره شده اند.

ذخیره تنظیمات قالب در جدول wp_options

 

گام ۴- فراخوانی تنظیمات در قالب سایت

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

<?php
$panel_settings = get_option( 'modiredev_panel_settings' );
?>
<ul>
    <li>
        <a href="https://twitter.com/<?php echo esc_attr( $panel_settings['twitter_url'] ); ?>"
           rel="nofollow"
           target="_blank">
            <span class="fab fa-twitter"></span>
        </a>
    </li>
    <li>
        <a href="https://facebook.com/<?php echo esc_attr( $panel_settings['facebook_url'] ); ?>"
           rel="nofollow"
           target="_blank">
            <span class="fab fa-facebook"></span>
        </a>
    </li>
    <li>
        <a href="https://instagram.com/<?php echo esc_attr( $panel_settings['instagram_url'] ); ?>"
           rel="nofollow"
           target="_blank">
            <span class="fab fa-instagram"></span>
        </a>
    </li>
</ul>

 

آپشن انتخاب رنگ در پنل تنظیمات

مطمئنا امکانات پنل تنظیمات محدود به چند تکست باکس ساده نخواهد بود، هر چقدر آپشن های بیشتری در نظر بگیرید به همان اندازه هم پیاده سازی آنها پیچیده تر خواهد شد.

یکی از ویژگی های مهمی که هر پنل تنظیماتی باید داشته باشد امکان انتخاب رنگ است، رنگ ها می تواند در بخش های مختلفی مثل پس زمینه، عناوین، آیکون ها و … استفاده شوند.

برای پیاده سازی این ویژگی ارزشمند مراحل زیر را به ترتیب انجام دهید:

گام ۱: آماده سازی wp-color-picker

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

برای این منظور ابتدا فایل wp-color-picker-alpha.min.js را دانلود کرده و در کنار فایل های جاوا اسکریپت قالب قرار دهید، ما این فایل را به دایرکتوری js  اضافه کردیم. سپس یک فایل جاوا اسکریپت با نام دلخواه مثلا admin.js ایجاد کنید، توجه داشته باشید که از این فایل فقط در پنل مدیریتی استفاده می شود.

حالا کدهای زیر را به فایل functions.php اضافه کنید.

function modiredev_admin_scripts( $hook )
{
    wp_enqueue_script( 'js_admin_panel',
        get_theme_file_uri( '/js/admin.js' ),
        array( 'jquery' ), '1.0', true );

    if ( $hook === 'toplevel_page_panel-settings' ) {
        wp_enqueue_style( 'wp-color-picker' );
        wp_enqueue_script( 'wp-color-picker' );
        wp_enqueue_script( 'wp-color-picker-alpha',
            get_theme_file_uri( '/js/wp-color-picker-alpha.min.js' ),
            array( 'wp-color-picker' ), '1.0', true );
    }
}

add_action( 'admin_enqueue_scripts', 'modiredev_admin_scripts' );

 

حواستان به شرط if باشد، panel-settings مقداری(menu_slug$) است که در هنگام تعریف پنل تنظیمات به عنوان آرگومان چهارم تابع add_menu_page مشخص کردیم، _toplevel_page رشته ای است که وردپرس به panel-settings اضافه کرده است.

با بررسی hook$ مطمئن شدیم که اسکریپت های انتخاب رنگ فقط در پنل تنظیمات قالب لود خواهد شد نه در کلیه بخش های پنل مدیریتی.

گام ۲: تعریف فیلد انتخاب رنگ در پنل تنظیمات

کدهای زیر به فایل options-panel-template.php اضافه کنید.

<h2>انتخاب رنگ</h2>
<table class="form-table">
    <tbody>
    <tr>
        <th scope="row">
            <label for="bg_color">رنگ پس زمینه:</label>
        </th>
        <td>
            <input type="text"
                   id="bg_color"
                   data-alpha="true"
                   name="panel_settings[bg_color]"
                   value="<?php echo esc_attr((isset($panel_settings_saved['bg_color']) ?
                                      $panel_settings_saved['bg_color'] : '')); ?>"
                   aria-required="true"
                   class="md-color-picker regular-text">
        </td>
    </tr>
    </tbody>
</table>

 

برای فعال سازی امکان انتخاب رنگ لازم است یک کلاس CSS با نام دلخواه مثلا md-color-picker و همچنین data-alpha=true به فیلد مربوطه اضافه کنید.

گام ۳: راه اندازی wp-color-picker

در نهایت کدهای زیر را در فایل admin.js قرار دهید، برای این منظور از کلاس md-color-picker مرحله قبل استفاده کردیم.

(function ( $ ) {
    $( '.md-color-picker' ).wpColorPicker();
})( jQuery );

 

پیشنهاد می کنیم مطلب آموزشی روش صحیح و اصولی استفاده از jQuery در وردپرس را مطالعه فرمائید.

گام ۴: نتیجه نهایی

در نهایت رنگ انتخاب شده به صورت هگزا(مثلا d4de5d#) در دیتابیس ذخیره می شود، برای فراخوانی تنظیمات مشابه موارد قبلی از تابع ()get_option استفاده کنید.

انتخاب رنگ در وردپرس با wp-color-picker

آپشن انتخاب تصویر در پنل تنظیمات

برای پیاده سازی امکان انتخاب تصویر می توانید از فرم انتخاب پرونده چند رسانه  ای یا Media Uploader وردپرس استفاده کنید.

مراحل اینکار را در چند مرحله بررسی می کنیم:

گام ۱: آماده سازی Media Uploader

مشابه آپشن انتخاب رنگ این مورد هم باید در پنل مدیریتی بارگذاری شود پس کدهای زیر را به فایل functions.php اضافه کنید.

function modiredev_admin_scripts( $hook )
{
    wp_enqueue_script( 'js_admin_panel',
        get_theme_file_uri( '/js/admin.js' ),
        array( 'jquery' ), '1.0', true );

    if ( $hook === 'toplevel_page_panel-settings' ) {
        wp_enqueue_media();
    }
}

add_action( 'admin_enqueue_scripts', 'modiredev_admin_scripts' );

 

هر آنچه که برای راه اندازی فرم انتخاب چند رسانه ای لازم است توسط تابع wp_enqueue_media  بارگذاری می شود.

گام ۲: تعریف فیلد انتخاب تصویر در پنل تنظیمات

کدهای زیر به فایل options-panel-template.php اضافه کنید.

<h2>انتخاب تصویر</h2>
<table class="form-table">
    <tbody>
    <tr>
        <th scope="row">
            <label for="md_image_upload_url">آدرس تصویر</label>
        </th>
        <td>
            <input type="text" name="panel_settings[img_url]"
                   id="md_image_upload_url"
                   class="regular-text"
                   value="<?php echo esc_attr((isset($panel_settings_saved['img_url']) ?
                             $panel_settings_saved['img_url'] : '')); ?>">
        </td>
    </tr>
    <tr>
        <td></td>
        <td>
            <img id="md_image_upload_preview"
                 src="<?php echo $panel_settings_saved['img_url']; ?>);">
        </td>
    </tr>
    <tr>
        <td>
            <input type="button"
                   class="button button-secondary md_image_upload"
                   value="افزودن تصویر">
            <input type="button"
                   class="button button-secondary md_image_upload_remove"
                   value="حذف تصویر">
        </td>
    </tr>
    </tbody>
</table>

 

توجه داشته باشید که از کلاس های CSS فیلد انتخاب تصویر در فایل admin.js استفاده می کنیم.

گام ۳: راه اندازی Media Uploader

در نهایت کدهای زیر را به admin.js اضافه کنید.

(function ( $ ) {
    let mediaUploader;
    $( 'body' ).on( 'click', '.md_image_upload', function (e) {

        e.preventDefault();

        if ( mediaUploader ) {
            mediaUploader.open();
            return;
        }

        mediaUploader = wp.media.frames.file_frame = wp.media({
            multiple: false
        });

        mediaUploader.on( 'select', function () {
            let attachment;
            attachment = mediaUploader.state().get( 'selection' ).first().toJSON();
            $( '#md_image_upload_url' ).val( attachment.url );
            $( '#md_image_upload_preview' ).attr( 'src', attachment.url );
        });

        mediaUploader.open();
    });

    $( 'body' ).on( 'click', '.md_image_upload_remove', function ( e ) {
        e.preventDefault();
        $( '#md_image_upload_url' ).val("");
        $( '#md_image_upload_preview' ).attr( 'src', '' );
    });
})( jQuery );

 

گام ۴: نتیجه نهایی

در نهایت آدرس تصویر در دیتابیس ذخیره می شود، برای فراخوانی تنظیمات مشابه موارد قبلی از تابع ()get_option استفاده کنید.

انتخاب تصویر در وردپرس با wp-media-uploader

جمع بندی

وقتی برای قالب یا افزونه خود تنظیمات متعدد و متنوعی در نظر می گیرید، پیاده سازی آنها به کمک Settings API پیچیدگی های کار را به شدت افزایش می دهد. در چنین سناریوهایی راه حل این آموزش مناسب و کارگشا خواهد بود، حتی می توانید آن را یک گام دیگر ارتقاء دهید و تنظیمات را از طریق Ajax ثبت کنید.

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

دانلود کدهای آموزش

 

نظرات و سوالات کاربران
  1. سلام وقت بخیر
    می خواستم بدونم بعد از اینکه مراحل فوق رو رفتیم، خب مسلما خروجی طبق توضیحات شما خواهد بود، حال اگر بخواییم اطلاعات بعضی از جاها مثل کپی رایت، شبکه مجازی عنوان هدر و… از طریق پنل تغییر بدیم، چه باید بکنیم؟!
    مثل توی پنل زدیم تغییر عنوان هدر ، توی کد هدر میشه از کد :

    رو بزاریم و …

    ممنون میشم راهنمایی کنید.
    تاجایی که من فهمیدم ما پنل رو ساختیم، فیلدهایی که میخواییم رو اضافه کردیم و ذخیر کردیم اما اون قسمت هایی که میخواییم توی سایت تغییر کنن رو مشخص نکردیم

    1. سلام دوست عزیز، در پنل تنظیمات هر آپشنی که وب سایتتون لازم داره رو تعریف کنید(متن کپی رایت، لینک شبکه های اجتماعی و …)، بعد به کمک تابع get_option اونها رو در بخش های مختلف قالب فراخوانی و استفاده کنید، پاسخ کامل شما با عنوان “فراخوانی تنظیمات در قالب سایت” به انتهای آموزش اضافه شد.

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

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