【WordPress】特定ユーザーに管理画面の機能を制限する方法|add_cap()による本当の権限制限

特定のユーザーだけ管理画面の一部機能を使えないようにしたい場面があります。この記事では、メニューを隠すだけでは終わらない、本当に機能を無効化する方法を解説します。

この記事でわかること

  • メニューを隠すだけでは機能は制限できていないという事実
  • add_cap($cap, false) で権限そのものを無効化する方法
  • メニュー非表示は権限制限の上に追加するUI整理として使う
  • 複数ユーザーに同じ制限をかけるならカスタムロールが管理しやすい
スポンサーリンク

remove_menu_page()だけでは機能を制限できない

remove_menu_page() で管理画面のメニュー項目を消す方法がよく紹介されますが、これは見た目上メニューを隠しているだけです。

メニューを消してもURLを直接開けば操作できてしまう
WordPressコアの wp-admin/plugins.php は、ページの冒頭でcurrent_user_can('activate_plugins')直接チェックしています。これはメニュー項目の有無とは無関係に動くため、対象ユーザーがまだ administrator ロールを持っている限り、/wp-admin/plugins.php のようなURLを直接開くだけでプラグインの有効化・無効化が普通にできてしまいますplugin_action_links フィルタでボタンを消しても同様です。「メニューを消す=機能を制限する」は誤解であり、本当に制限するには権限(Capability)そのものを操作する必要があります

本質的な制限方法:ユーザーの権限(Capability)を無効化する

特定のユーザーだけ特定の権限を使えなくするには、add_cap($cap, false) を使います。false を明示的に追加することで、administrator ロールから継承している権限をそのユーザーだけ上書きして無効化できます。

functions.php:特定ユーザーの権限を本当に無効化する
add_action( 'admin_init', function () {
    $restricted_user_id = 2;
    $target_caps = array(
        'activate_plugins',    // プラグインの有効化・無効化
        'edit_theme_options',  // 外観メニュー全般
        'list_users',          // ユーザー一覧
        'edit_users',          // ユーザー編集
        'manage_options',      // 設定メニュー
    );

    $user = get_user_by( 'id', $restricted_user_id );
    if ( ! $user ) {
        return;
    }

    foreach ( $target_caps as $cap ) {
        // 既にfalseで上書き済みならadd_capを呼ばない(毎リクエストの無駄なDB書き込みを防ぐ)
        if ( ! isset( $user->caps[ $cap ] ) || $user->caps[ $cap ] !== false ) {
            $user->add_cap( $cap, false );
        }
    }
} );
なぜ remove_cap() ではなく add_cap($cap, false) なのか
WP_User::remove_cap() は、そのユーザー自身に明示的に設定された権限しか削除できません。administrator などの権限はロール側の権限テーブルから継承されているため、remove_cap('activate_plugins') を呼んでも何も起こりません。WordPressは「ロールの権限」→「ユーザー個別の権限」の順にマージし、後から上書きしたユーザー個別の値が優先されるため、継承した権限を打ち消すには add_cap($cap, false)明示的に false を追加する必要があります。

メニュー非表示は権限制限の上に追加するUI整理として使う

権限そのものを無効化したうえで、使えないメニュー項目を見せないようにすると、対象ユーザーが混乱しにくくなります。あくまで上記の権限制限とセットで使うUI上の仕上げです。

functions.php:権限を外したメニューを非表示にする(UI整理)
add_action( 'admin_menu', function () {
    $restricted_user_id = 2;

    if ( get_current_user_id() !== $restricted_user_id ) {
        return;
    }

    remove_menu_page( 'plugins.php' );        // プラグイン
    remove_menu_page( 'users.php' );          // ユーザー
    remove_menu_page( 'themes.php' );         // 外観
    remove_menu_page( 'options-general.php' ); // 設定
}, 999 );

複数ユーザーに同じ制限をかけるならカスタムロールが管理しやすい

制限対象が1人だけなら add_cap() で十分ですが、複数のユーザーに同じ制限をかけたい場合は、必要な権限だけを持つカスタムロールを作って割り当てる方が管理しやすくなります。

functions.php:制限付きのカスタムロールを作成
add_action( 'init', function () {
    if ( get_role( 'restricted_editor' ) ) {
        return; // 既に作成済みなら何もしない
    }
    add_role( 'restricted_editor', '制限付き編集者', array(
        'read'         => true,
        'edit_posts'   => true,
        'upload_files' => true,
        // activate_plugins・manage_options等は含めない=そもそも持たない
    ) );
} );
コード編集が不安な場合はプラグインでも設定可能
「User Role Editor」のような権限管理プラグインを使うと、管理画面から視覚的にロールごとの権限を編集できます。ロール設計の考え方自体はコードで実装する場合と同じです。

関連する権限制限の実装

固定ページの編集だけをピンポイントで制限したい場合は管理者権限以外のユーザーは固定ページを編集できないようにする方法で、admin_init フックによるリダイレクトを使った実装例を解説しています。

よくある質問(FAQ)

Qremove_cap()を呼んだのに権限が制限されません。
Aremove_cap()そのユーザー自身に明示的に設定された権限しか削除できません。administrator ロールから継承している権限には効果がないため、add_cap($cap, false) で明示的に false を追加して上書きしてください。
Q一般ユーザーが管理画面にアクセスできないようにするには?
Aadd_action('admin_init', ...) フックで current_user_can() を使ってロールを確認し、許可しないユーザーを wp_safe_redirect() でフロントエンドにリダイレクトします。
Q管理画面のメニューを特定のロールに対して非表示にするには?
Aremove_menu_page()remove_submenu_page()admin_menu アクション内でロールチェックと組み合わせて使います。ただしこれは表示を隠すだけなので、必ず add_cap() による権限無効化とセットで使ってください。
Q投稿者ロールが自分の記事しか編集できないようにするデフォルトの動作は?
AWordPressの author ロールは自分の記事のみ編集・削除できます。他ユーザーの記事を編集できるのは editor 以上です。カスタム制限は map_meta_cap フィルターで詳細に設定できます。

まとめ

  • 誤解remove_menu_page() はメニューを隠すだけで機能は制限できない
  • 本当の制限add_cap($cap, false) で権限そのものを無効化
  • 注意remove_cap() はロール継承の権限には効かない
  • 複数ユーザー:必要な権限だけのカスタムロールを作る方が管理しやすい

メニューを隠すだけで満足せず、権限そのものを無効化してはじめて「機能を制限した」と言えることを覚えておいてください。