پروژه‌ای را به یاد می‌آورم که در آن، یک آموزشگاه آنلاین می‌خواست «مدرسان» به پیشخوان دسترسی داشته باشند ولی نه به همهٔ بخش‌ها. تیم قبلی، بدون تعریف نقش سفارشی، نقش پیش‌فرض «نویسنده» را به مدرسان داده بود. نتیجه؟ مدرسان می‌توانستند بخش‌هایی از پیشخوان را که نباید، ببینند و حتی در برخی موارد، داده‌هایی را تغییر دهند که فقط مدیر سایت باید تغییر می‌داد. راه‌حل در آن پروژه، یک اسنیپت کوچک بود: تعریف نقش «wphk_teacher» با مجموعه‌ای دقیق از دسترسی‌ها که فقط اجازهٔ مدیریت دوره‌ها، جلسات و دانش‌آموزان را می‌داد. آن تجربه، یک باور رایج را در ذهن من اصلاح کرد: خیلی از پروژه‌های وردپرسی، به‌جای «نقش مناسب»، «نقش پیش‌فرض نزدیک‌ترین» را انتخاب می‌کنند و همین موضوع، هم امنیت و هم تجربهٔ کاربری را در بلندمدت خراب می‌کند. در این مقاله، مسیر عملی قطعه کد افزودن نقش کاربری جدید وردپرس را با هم مرور می‌کنیم: چرا نقش سفارشی لازم است، چگونه با تابع add_role ساخته می‌شود، چطور دسترسی‌ها را دقیق تعریف کنیم، و چه ملاحظات پایداری و امنیتی در این حوزه وجود دارد. اگر با مفهوم پایهٔ اسنیپت آشنا نیستید، پیش از ادامه قطعه کد وردپرس چیست و چگونه از آن استفاده کنیم نقطهٔ شروع بهتری است. برای درک عمیق‌تر توابع مرتبط، توابع وردپرس برای مدیریت نقش‌ها و دسترسی‌ها مرجع کاملی است.

چرا نقش سفارشی، یک تصمیم ساختاری است نه یک تنظیم ساده

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

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

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

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

نقش کاربری، یک قرارداد بین سایت و کسی است که در آن کار می‌کند. اگر این قرارداد شفاف نباشد، هم سایت آسیب می‌بیند و هم کاربر سرگردان می‌شود.

نقش و دسترسی: تفاوت کلیدی که اکثر پروژه‌ها آن را قاطی می‌کنند

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

نقش (Role): یک برچسب بزرگ است که به یک یا چند کاربر تخصیص می‌یابد و مجموعه‌ای از دسترسی‌ها را با خود حمل می‌کند. مثال: نقش «مدیر»، «ویرایشگر»، «نویسنده». یک کاربر می‌تواند بیش از یک نقش داشته باشد.

دسترسی (Capability): یک توانایی منفرد است که یا به یک نقش تخصیص می‌یابد یا مستقیماً به یک کاربر. مثال: edit_posts، publish_posts، manage_options. کد وردپرس همیشه براساس capability تصمیم می‌گیرد، نه براساس role.

ترجمهٔ این تفکیک در عمل: وقتی می‌گویید «این کاربر مدیر است»، در واقع می‌گویید «این کاربر capabilityهای manage_options، edit_users و ده‌ها capability دیگر را دارد». تابع current_user_can هیچ‌وقت نقش را چک نمی‌کند، فقط capability را. تجربهٔ من می‌گوید بیشتر باگ‌های امنیتی در پروژه‌های وردپرسی از همین‌جا آمده که توسعه‌دهنده به‌جای بررسی capability، مستقیماً نقش را چک کرده است.

مثال از تفاوت عملی: در پروژه‌ای، توسعه‌دهنده‌ای می‌خواست همهٔ «ویرایشگرها» بتوانند محصولات را ویرایش کنند. کدی نوشت که فقط نقش editor را چک می‌کرد. نتیجه: اگر مدیری edit_products را به نقش دیگری می‌داد، آن کد بی‌اثر می‌شد. راه‌حل درست: چک capability، نه نقش. الگوی دقیق این کار در توابع وردپرس برای مدیریت نقش‌ها و دسترسی‌ها آمده است.

نقش‌های پیش‌فرض وردپرس: نقشهٔ اولیه

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

نقشسطح دسترسیکاربرد رایج
administratorکامل؛ دسترسی به همه‌چیزمدیر سایت
editorمدیریت همهٔ نوشته‌ها، برگه‌ها و دیدگاه‌هاسردبیر محتوایی
authorنوشتن، انتشار و ویرایش نوشته‌های خودنویسندهٔ محتوا
contributorنوشتن پیش‌نویس بدون انتشارنویسندهٔ تازه‌کار یا مهمان
subscriberفقط ورود و مدیریت پروفایل خودکاربر عادی سایت

سه نکتهٔ کلیدی در این جدول. اول، هر نقش، مجموعه‌ای از capabilityها است که در وردپرس به‌طور پیش‌فرض تعریف شده‌اند. لیست کامل این capabilityها در مستندات رسمی وردپرس و در مقالهٔ توابع وردپرس برای مدیریت نقش‌ها و دسترسی‌ها آمده است. دوم، ووکامرس سه نقش جدید (customer، shop_manager، shop_vendor) به این فهرست اضافه می‌کند که در پروژه‌های فروشگاهی مهم است. سوم، افزونه‌های دیگر هم می‌توانند نقش‌های خودشان را اضافه کنند؛ قبل از ساختن نقش سفارشی، بررسی کنید که در فهرست نقش‌های فعلی، گزینهٔ نزدیک به نیاز شما وجود ندارد.

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

افزودن نقش سفارشی با تابع add_role

تابع اصلی برای افزودن نقش سفارشی، add_role است. این تابع سه پارامتر می‌گیرد: نام یکتای نقش (slug)، نام نمایشی و آرایه‌ای از capabilityها. نمونهٔ ساده:

/**
 * Snippet: Register a custom teacher role.
 *
 * @since 2026-09-16
 * @author WordPressKar
 *
 * Purpose: Register a 'teacher' role with restricted capabilities.
 * Location: mu-plugins directory or activation hook of custom plugin.
 */

add_action( 'init', 'wphk_register_teacher_role' );

function wphk_register_teacher_role() {
    if ( get_role( 'wphk_teacher' ) ) {
        return;
    }

    add_role(
        'wphk_teacher',
        'مدرس',
        array(
            'read'                     => true,
            'edit_posts'               => true,
            'edit_published_posts'     => true,
            'publish_posts'            => true,
            'upload_files'             => true,
            'edit_wphk_courses'        => true,
            'edit_others_wphk_courses' => false,
            'publish_wphk_courses'     => true,
        )
    );
}

پنج نکتهٔ کلیدی در همین نمونه. اول، بررسی وجود نقش با get_role در ابتدا: اگر نقش قبلاً وجود دارد، از بازنویسی خودداری می‌شود. این نکته، از پاک‌شدن capabilityهای اضافه‌شدهٔ دستی جلوگیری می‌کند. دوم، استفاده از پیشوند اختصاصی wphk_teacher برای نام نقش که تعارض با نقش‌های افزونه‌های دیگر را به حداقل می‌رساند. سوم، استفاده از هوک init به‌عنوان جایگاه اجرا برای این کد؛ این هوک نقطهٔ استاندارد ثبت نقش‌های سفارشی است. چهارم، capabilityهای محتوایی عمومی مثل edit_posts و upload_files که به کاربر اجازهٔ کار با نوشته‌ها و رسانه را می‌دهد. پنجم، capabilityهای اختصاصی مثل edit_wphk_courses که با نوع نوشتهٔ سفارشی شما مرتبط است. نحوۀ دقیق اتصال به این هوک در نحوه استفاده از add_action در وردپرس آمده است.

یک نکتهٔ ظریف: capabilityهای اختصاصی مثل edit_wphk_courses به‌طور خودکار وجود ندارند؛ آنها را باید در زمان تعریف نوع نوشتهٔ سفارشی با map_meta_cap یا capability_type فعال کنید. اگر این کار را نکنید، capability سفارشی شما در جدول capabilityها ثبت نمی‌شود و کد شما به‌سادگی بی‌اثر می‌شود. توضیح جامع این مکانیزم در ساخت نوع نوشته سفارشی در وردپرس آمده است.

تعریف دقیق دسترسی‌ها: کدام capability برای کدام کار

انتخاب capabilityهای درست، بخش دشوارتر این کار است. در تجربهٔ من، فهرست زیر پرکاربردترین capabilityهای وردپرس است که باید بشناسید:

Capabilityهای محتوایی

  • read: ورود به پیشخوان و مشاهدهٔ پروفایل شخصی. این capability پایه است و باید تقریباً برای هر نقشی که به پیشخوان نیاز دارد، فعال باشد.
  • edit_posts: ویرایش نوشته‌های خود.
  • edit_others_posts: ویرایش نوشته‌های کاربران دیگر.
  • publish_posts: انتشار نوشتهٔ خود بدون نیاز به تأیید.
  • delete_posts: حذف نوشته‌های خود.
  • upload_files: آپلود فایل در کتابخانهٔ رسانه.

Capabilityهای مدیریتی

  • manage_options: دسترسی به تنظیمات سایت و افزونه‌ها. این capability، حساس‌ترین capability است و باید فقط به مدیر یا مدیران ارشد داده شود.
  • edit_users: مدیریت کاربران.
  • manage_categories: مدیریت دسته‌بندی‌ها و برچسب‌ها.

Capabilityهای مرتبط با افزونه‌ها

  • ووکامرس: manage_woocommerce، edit_shop_orders، view_woocommerce_reports.
  • المنتور: edit_posts_with_elementor.
  • سئو: بسته به افزونه، capabilityهای مختلف برای مدیریت تنظیمات سئو.

سه نکتهٔ کلیدی در انتخاب capabilityها. اول، برای هر قابلیت، کمترین capability لازم را انتخاب کنید. اگر کاربر فقط باید پیش‌نویس بنویسد، edit_posts را بدهید، ولی publish_posts را ندهید. دوم، capabilityهای افزونه‌های دیگر را در زمان ثبت نقش اضافه کنید. اگر نقش شما نیاز به دسترسی به ووکامرس دارد، manage_woocommerce را اضافه کنید. سوم، در فهرست نهایی، capabilityهای غیرضروری را از ابتدا ندهید. افزودن بعدی، همیشه آسان‌تر از حذف کردن است.

در انتخاب capabilityها، سؤال درست این نیست «کاربر چه چیزی می‌تواند بکند؟» سؤال درست این است «کاربر در حداقل حالت، چه چیزی باید بکند؟» هر capability اضافه، یک مسئولیت اضافه است.

زمان‌بندی: چرا register_activation_hook

در بخش قبل، مثال ما از هوک init استفاده می‌کرد. این رویکرد ساده است ولی یک اشکال دارد: در هر بار بارگذاری سایت، تابع شما اجرا می‌شود و وجود نقش را بررسی می‌کند. برای سایت‌های پربازدید، این بار اضافه ممکن است محسوس باشد. راه‌حل حرفه‌ای‌تر، استفاده از هوک فعال‌سازی افزونه است:

/**
 * در فایل اصلی افزونهٔ اختصاصی:
 */

register_activation_hook( __FILE__, 'wphk_activate_plugin' );

function wphk_activate_plugin() {
    wphk_register_teacher_role();
    wphk_add_custom_capabilities();
}

function wphk_register_teacher_role() {
    if ( get_role( 'wphk_teacher' ) ) {
        return;
    }

    add_role( 'wphk_teacher', 'مدرس', array(
        'read'                 => true,
        'edit_posts'           => true,
        'publish_posts'        => true,
        'upload_files'         => true,
    ) );
}

function wphk_add_custom_capabilities() {
    $admin = get_role( 'administrator' );
    if ( $admin ) {
        $admin->add_cap( 'manage_wphk_courses' );
    }
}

سه نکتهٔ کلیدی در این الگو. اول، استفاده از register_activation_hook که فقط در زمان فعال‌سازی افزونه اجرا می‌شود، نه در هر بار بارگذاری سایت. این رویکرد، بار پردازش اضافه را حذف می‌کند. دوم، در تابع فعال‌سازی، هم نقش جدید اضافه می‌شود و هم capabilityهای اضافی به مدیر سایت تخصیص می‌یابد. سوم، اگر در آینده بخواهید capability جدیدی به نقش موجود اضافه کنید، آن را در یک تابع جدا با نسخه‌بندی جداگانه اجرا کنید تا افزونه‌های فعال در سایت‌های مختلف، به‌درستی به‌روزرسانی شوند. توضیح تفصیلی این الگو در هوک‌های وردپرس در توسعه افزونه چه کاربردی دارند آمده است.

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

حذف نقش سفارشی: کی، چگونه و با چه احتیاطی

حذف یک نقش سفارشی، به‌اندازهٔ افزودن آن، نیازمند دقت است. سه قاعدهٔ کلیدی در این حوزه:

قاعدهٔ اول: هرگز نقش را بدون بررسی حذف نکنید

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

add_action( 'admin_init', 'wphk_safe_remove_teacher_role' );

function wphk_safe_remove_teacher_role() {
    $role = get_role( 'wphk_teacher' );
    if ( ! $role ) {
        return;
    }

    $users_with_role = get_users( array(
        'role'   => 'wphk_teacher',
        'number' => 1,
        'fields' => 'ID',
    ) );

    if ( ! empty( $users_with_role ) ) {
        return;
    }

    remove_role( 'wphk_teacher' );
}

سه نکتهٔ کلیدی در این الگو: اول، بررسی وجود کاربران با این نقش پیش از حذف. دوم، استفاده از پارامتر number => 1 که از کوئری سنگین روی همهٔ کاربران جلوگیری می‌کند و با یک کاربر داشتن، جلوی حذف را می‌گیرد. سوم، اگر کاربران با این نقش وجود دارند، تابع در سکوت از ادامه دست می‌کشد؛ نمی‌خواهیم چیزی حذف شود و نیازی به پیام خطا نیست.

قاعدهٔ دوم: نقش را در غیرفعال‌سازی افزونه حذف نکنید

بسیاری از افزونه‌ها در زمان غیرفعال‌سازی، نقش‌های سفارشی خود را حذف می‌کنند. این رویکرد، در ابتدا منطقی به‌نظر می‌رسد ولی در عمل فاجعه‌بار است: اگر کاربری این نقش را داشته باشد و شما افزونه را موقتاً غیرفعال کنید، کاربر بدون نقش می‌ماند و پس از فعال‌سازی مجدد، دسترسی‌هایش را از دست می‌دهد. توصیهٔ من: نقش را در غیرفعال‌سازی حذف نکنید و تنها در زمان uninstall (حذف کامل افزونه) آن را در نظر بگیرید — و همان‌جا هم با احتیاط کامل.

قاعدهٔ سوم: پیام هشدار به مدیر

اگر به هر دلیلی تصمیم گرفتید نقش را در زمان uninstall حذف کنید، حتماً یک پیام هشدار به مدیر سایت نشان دهید که به او بگوید نقش در حال حذف است و کاربران با این نقش باید ابتدا به نقش دیگری منتقل شوند. این پیام می‌تواند در قالب یک تابع ساده در admin_notices نمایش داده شود. الگوهای مشابه برای اطلاع‌رسانی در پیشخوان در قطعه کد افزودن ستون سفارشی به مدیریت وردپرس آمده است.

اختصاص نقش به کاربران: چه دستی چه برنامه‌ای

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

روش اول: اختصاص دستی از پیشخوان

ساده‌ترین راه: در بخش «کاربران» پیشخوان، وارد پروفایل کاربر شوید و از منوی «نقش» در بخش «نقش کاربری»، نقش سفارشی خود را انتخاب کنید. این روش برای تعداد کم کاربران مناسب است.

روش دوم: اختصاص برنامه‌ای براساس شرط

در پروژه‌های عضویت‌محور، اغلب نیاز دارید که براساس یک شرط خاص (مثلاً تکمیل خرید یک دوره)، نقش کاربر به‌طور خودکار تغییر کند. این کار با تابع set_role روی شیء کاربر انجام می‌شود:

add_action( 'woocommerce_order_status_completed', 'wphk_assign_teacher_role' );

function wphk_assign_teacher_role( $order_id ) {
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }

    foreach ( $order->get_items() as $item ) {
        $product_id = $item->get_product_id();
        if ( 123 !== $product_id ) {
            continue;
        }

        $user_id = $order->get_user_id();
        if ( $user_id ) {
            $user = new WP_User( $user_id );
            $user->add_role( 'wphk_teacher' );
        }
    }
}

سه نکتهٔ کلیدی: اول، استفاده از متد add_role به‌جای set_role که نقش‌های فعلی کاربر را حذف نمی‌کند. اگر می‌خواهید نقش فعلی را جایگزین کنید، از set_role استفاده کنید. دوم، بررسی وجود کاربر پیش از تغییر نقش. سوم، توجه به این نکته که در ووکامرس، سفارش‌ها در نسخه‌های جدید ممکن است شامل کاربران مهمان باشند که user_id صفر دارند. تحلیل جامع این حوزه در مدیریت سفارش‌ها در ووکامرس آمده است.

روش سوم: اختصاص انبوه با WP-CLI

برای اختصاص نقش به تعداد زیادی کاربر، WP-CLI ابزار کارآمدی است:

wp user add-role 42 wphk_teacher

این دستور، نقش wphk_teacher را به کاربر با شناسهٔ ۴۲ اضافه می‌کند. برای اختصاص به همهٔ کاربران با یک شرط خاص، می‌توانید از wp user list به‌همراه یک اسکریپت کوچک استفاده کنید. این روش در پروژه‌هایی که کاربران زیادی دارند و می‌خواهید به‌طور دسته‌ای نقش اختصاص دهید، کاربردی است.

ترکیب نقش‌ها: امکان‌سنجی و محدودیت‌ها

وردپرس اجازه می‌دهد که یک کاربر بیش از یک نقش داشته باشد. این ویژگی، در پروژه‌های پیچیده به‌کار می‌آید؛ مثلاً یک کاربر می‌تواند هم «نویسنده» باشد و هم «مدرس». مجموع capabilityهای همهٔ نقش‌ها به کاربر تخصیص می‌یابد. الگوی افزودن نقش به‌جای جایگزینی:

$user = new WP_User( $user_id );
$user->add_role( 'wphk_teacher' );

سه نکتهٔ کلیدی: اول، متد add_role نقش جدید را اضافه می‌کند، ولی نقش‌های قبلی را حفظ می‌کند. اگر می‌خواهید نقش‌ها را جایگزین کنید، از set_role استفاده کنید. دوم، در نمایش نقش کاربر در پیشخوان، وردپرس تمام نقش‌های کاربر را نشان می‌دهد. اگر این نمایش در فرآیند کاری شما اختلال ایجاد می‌کند، با یک اسنیپت کوچک می‌توانید آن را تغییر دهید. سوم، در چک‌های دسترسی، همیشه از capability استفاده کنید نه نقش؛ چون یک کاربر ممکن است چند نقش داشته باشد و بررسی نقش‌به‌نقش باعث خطاهای ظریف می‌شود. اصول تفصیلی این تفکیک در توابع وردپرس برای مدیریت نقش‌ها و دسترسی‌ها آمده است.

افزونهٔ مدیریت نقش یا اسنیپت: کدام برای چه پروژه‌ای

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

معیاراسنیپتافزونهٔ مدیریت نقش
سایت با نقش‌های ثابتگزینهٔ بهتراضافه‌بار
سایت با نقش‌های متغیر و تغییرات مکررنیازمند بازنویسی کدگزینهٔ بهتر
سایت با مدیر غیرفنیدشوار برای مدیریتگزینهٔ بهتر
سایت با نقش‌های پیچیده و ترکیبیپایدارترگزینهٔ خوب
پروژهٔ مشتری با تحویل بلندمدتگزینهٔ بهتر (مستندسازی)گزینهٔ پذیرفتنی

الگوی عملی من در پروژه‌های خودم: اگر سایت مشتری تیم ثابتی دارد و نقش‌ها تغییر نمی‌کنند، از اسنیپت استفاده می‌کنم چون سبک‌تر و پایدارتر است. اگر مشتری خودش تیم را مدیریت می‌کند و ممکن است نقش‌ها را عوض کند، از یک افزونهٔ سبک مدیریت نقش مثل Members یا User Role Editor استفاده می‌کنم. در هر دو حالت، توصیهٔ من این است که پس از تحویل پروژه، ساختار نقش‌ها و capabilityهای هرکدام را در یک مستند کوتاه برای مشتری بنویسید.

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

محل درست قرارگیری این اسنیپت

مانند همهٔ اسنیپت‌های وردپرس، محل قرارگیری این کد هم تصمیم مهمی است. سه گزینه پیش روی شماست:

گزینهٔ اول: افزونهٔ اختصاصی یا mu-plugins. این گزینه، پایدارترین مسیر برای نقش‌های سفارشی است؛ چون نقش کاربری بخشی از ساختار امنیتی سایت است و باید مستقل از قالب زندگی کند. اگر با ساختار افزونهٔ اختصاصی آشنا نیستید، کدنویسی اختصاصی برای افزونه وردپرس و ساختار فایل‌های یک افزونه استاندارد وردپرس مراجع کاملی هستند.

گزینهٔ دوم: چایلد تم. اگر پروژهٔ شما ساده است و افزونهٔ اختصاصی ندارید، چایلد تم گزینهٔ قابل‌قبولی است؛ ولی توجه داشته باشید که نقش کاربری معمولاً بخشی از ساختار سایت است، نه بخشی از ظاهر آن. در تعویض قالب، این کد از بین می‌رود و ممکن است کسی متوجه نشود. تفاوت‌ها و کاربردهای چایلد تم در قالب وردپرس چایلد چیست و چه زمانی به آن نیاز داریم آمده است.

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

الگوی عملی من در پروژه‌های خودم: تمام کدهای مرتبط با نقش‌ها و capabilityها را در یک افزونهٔ اختصاصی کوچک به نام «wphk-roles» نگه می‌دارم که هم ثابت‌های نقش را در خود دارد و هم منطق تخصیص خودکار. این ساختار، در پروژه‌های چندساله، پایداری و مستندسازی را تضمین می‌کند. برای دیدن فهرست گسترده‌تری از اسنیپت‌های کاربردی، بهترین قطعه کدهای کاربردی وردپرس برای سایت‌ها مرجع خوبی است.

اشتباهات رایج در افزودن نقش سفارشی

در بازبینی سایت‌های مختلف، شش اشتباه تکراری در این حوزه دیده‌ام که هرکدام درس‌آموز است:

اشتباهپیامد واقعیاصلاح
چک نقش به‌جای capability در کد سفارشیکاربر با نقش ترکیبی، دسترسی‌هایش بی‌اثر می‌شوداستفاده از current_user_can با capability
حذف نقش در غیرفعال‌سازی افزونهکاربران بدون نقش می‌مانندحذف فقط در uninstall با بررسی کاربران
نبود بررسی وجود نقش پیش از add_rolecapabilityهای اضافی پاک می‌شوندچک get_role در ابتدا
نبود پیشوند اختصاصی در نام نقشتعارض با نقش‌های افزونه‌های دیگرپیشوند یکتا مثل wphk_
اعطای capabilityهای زیاد از ابتداسطح حمله بالا، امنیت ضعیفکمترین capability لازم، افزودن تدریجی
نبود مستندسازی نقش‌هافراموشی دلیل هر نقش در ماه‌های بعدمستند کوتاه با نام، هدف و capabilityها

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

دو پروندهٔ واقعی از پروژه‌ها

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

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

همان پروژهٔ ابتدای مقاله. آموزشگاه آنلاین، مدرسان را با نقش «نویسنده» به پیشخوان اضافه کرده بود. نتیجه: مدرسان به بخش‌هایی از پیشخوان دسترسی داشتند که نباید (مثل بخش تنظیمات افزونه‌ها) و حتی در برخی موارد، داده‌هایی را تغییر داده بودند که فقط مدیر باید تغییر می‌داد. راه‌حل: تعریف نقش wphk_teacher با capabilityهای محدود، انتقال مدرسان به این نقش، و حذف دسترسی‌های اضافی. نتیجه در یک ماه: هیچ حادثهٔ امنیتی از مدرسان گزارش نشد و تجربهٔ کاری‌شان هم بهبود یافت چون فقط بخش‌های مرتبط را می‌دیدند. تحلیل تفصیلی این نوع بهینه‌سازی امنیتی در راهنمای امنیت وردپرس برای مبتدیان آمده است.

پروندهٔ دوم: فروشگاهی که با نقش سفارشی، صفِ پشتیبانی را کوتاه کرد

در یک فروشگاه ووکامرسی، تیم پشتیبانی روزانه با حجم زیادی از سفارش‌ها کار می‌کرد ولی به‌دلیل نداشتن نقش سفارشی، از نقش «مدیر» استفاده می‌کرد که دسترسی‌های بیش‌ازحد و خطرناکی می‌داد. راه‌حل: تعریف نقش wphk_support با capabilityهایی مثل read، edit_shop_orders، view_woocommerce_reports که فقط برای پشتیبانی لازم بود. نتیجه: پشتیبانی با تمرکز روی سفارش‌ها کار کرد، خطاهای ناخواسته حذف شد، و هم‌زمان امنیت فروشگاه افزایش یافت. تجربهٔ مشابه در حوزهٔ ووکامرس در مدیریت سفارش‌ها در ووکامرس آمده است.

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

درس‌ها و مسیر پیشنهادی

قطعه کد افزودن نقش کاربری جدید وردپرس، یکی از پرتکرارترین نیازهای پروژه‌های حرفه‌ای است. سه ستون این کار: تعریف نقش با add_role و بررسی وجود آن پیش از افزودن، انتخاب دقیق capabilityها براساس اصل «کمترین لازم»، و پیاده‌سازی در زمان فعال‌سازی افزونه به‌جای هر بار بارگذاری سایت. سه ملاحظهٔ کلیدی (تفکیک نقش از capability، پرهیز از حذف نقش در غیرفعال‌سازی، مستندسازی دقیق) تفاوت بین یک پروژهٔ حرفه‌ای و یک پروژهٔ آماتور را می‌سازند. و محل درست این اسنیپت، افزونهٔ اختصاصی یا mu-plugins است، نه فایل قالب والد.

گام بعدی عملی که پیشنهاد می‌کنم: در همین امروز، فهرست کاربران سایت خود را باز کنید و ببینید آیا نقش هرکدام با نیاز واقعی‌اش مطابقت دارد. اگر می‌بینید که برخی کاربران دسترسی بیش از حد لازم دارند یا با نقش نامناسب کار می‌کنند، همین هفته می‌توانید با یک اسنیپت کوچک، نقش مناسب بسازید و آن‌ها را منتقل کنید. اگر تجربه‌ای با افزودن نقش سفارشی داشته‌اید — به‌ویژه اگر نقش پیچیده‌ای با ترکیب capabilityهای متعدد ساخته‌اید یا اگر در پروژه‌ای به نکته‌ای برخورده‌اید که در این مقاله پوشش داده نشده — برای من جالب است بدانید چطور حلش کردید. تجربهٔ خودتان را در دیدگاه‌ها بنویسید؛ به‌ویژه اگر روش تمیزی برای مستندسازی نقش‌ها و capabilityها پیدا کرده‌اید. 🔐