特定の固定ページだけを、特定のユーザーにのみ編集させたい場合の実装方法を解説します。プラグインを使わずに functions.php だけで実現できますが、よく紹介される実装には見落とされがちな落とし穴があるため、確実に動作する方法をあわせて解説します。
この記事でわかること
user_has_capでedit_postを直接書き換えても効果が無い理由map_meta_capフィルターを使った確実な実装方法- 特定のユーザーに全ての固定ページ編集を許可する方法
user_has_capでedit_postを直接書き換えても効果が無い理由
edit_postは「メタ権限」であり$allcapsのキーには使えない
user_has_cap フィルター内で $allcaps['edit_post'] = true; のように書き換える実装がよく紹介されますが、これは実際の権限判定に一切影響しません。本番WPコアで確認したところ、current_user_can('edit_post', $post_id) の判定は次の順で行われます。①edit_post のような「メタ権限」を map_meta_cap() が投稿の種類や所有者に応じて具体的なプリミティブ権限(edit_pages・edit_others_pages など)に変換する。②その変換後のプリミティブ権限名だけを使って$allcaps(user_has_capフィルター適用後)をチェックする。edit_post というキー自体は一度も参照されません。そのため $allcaps['edit_post'] をどう書き換えても無意味であり、投稿単位で権限を制御したい場合は map_meta_cap フィルターを使う必要があります。map_meta_capで特定ページを特定ユーザーにのみ許可する(正しい実装)
map_meta_cap フィルターは、投稿IDなどの引数を直接受け取れるため、投稿単位での権限制御に適した正しい介入ポイントです。許可されたユーザー以外には do_not_allow という特殊な権限を返すことで、確実に編集・削除を拒否できます。
functions.php:特定の固定ページを特定ユーザーにのみ許可
function restrict_page_editing( $caps, $cap, $user_id, $args ) {
// edit_post / delete_post の判定にだけ介入する
if ( ! in_array( $cap, array( 'edit_post', 'delete_post' ), true ) || empty( $args[0] ) ) {
return $caps;
}
$post_id = $args[0];
$post = get_post( $post_id );
if ( ! $post || 'page' !== $post->post_type ) {
return $caps;
}
$allowed_page_ids = array( 10, 20, 30 ); // 制限対象の固定ページID
$allowed_user_ids = array( 1, 2, 3 ); // 編集を許可するユーザーID
// 制限対象のページでなければ何もしない(通常の権限判定に任せる)
if ( ! in_array( $post_id, $allowed_page_ids, true ) ) {
return $caps;
}
// 許可リストに無いユーザーは強制的に拒否する
if ( ! in_array( $user_id, $allowed_user_ids, true ) ) {
return array( 'do_not_allow' );
}
return $caps;
}
add_filter( 'map_meta_cap', 'restrict_page_editing', 10, 4 );
制限対象外のページ・ユーザーには影響しない
$allowed_page_ids に含まれないページは $caps をそのまま返すため、通常どおりの権限(ロールに応じた既定の編集可否)で動作します。制限がかかるのは、指定したページIDに対してだけです。特定のユーザーにすべての固定ページ編集を許可する
個別のページ単位ではなく、特定のユーザーに固定ページ全般の編集権限を付与したい場合は、user_has_cap フィルターでプリミティブ権限を直接付与します。こちらは edit_pages 等の実在するプリミティブ権限名を使っているため、正しく動作します。
functions.php:特定ユーザーに全固定ページの編集を許可
function allow_user_edit_all_pages( $allcaps, $caps, $args ) {
$allowed_user_ids = array( 1, 2, 3 ); // 許可するユーザーID
$current_user_id = get_current_user_id();
if ( in_array( $current_user_id, $allowed_user_ids, true ) ) {
$allcaps['edit_pages'] = true;
$allcaps['edit_others_pages'] = true;
$allcaps['delete_pages'] = true;
$allcaps['delete_others_pages'] = true;
}
return $allcaps;
}
add_filter( 'user_has_cap', 'allow_user_edit_all_pages', 10, 3 );
注意事項
カスタムコード追加前は必ずバックアップを
権限まわりのコードを誤ると、意図しないユーザーの編集を許可・拒否してしまう可能性があります。追加前に必ずテーマファイルのバックアップを取り、ユーザーID・固定ページIDは実際のものに置き換えてから使用してください。
権限まわりのコードを誤ると、意図しないユーザーの編集を許可・拒否してしまう可能性があります。追加前に必ずテーマファイルのバックアップを取り、ユーザーID・固定ページIDは実際のものに置き換えてから使用してください。
関連する権限制限の実装
よくある質問(FAQ)
Q特定のユーザーのみ特定の固定ページを編集できるようにするには?
A
map_meta_capフィルターを使い、対象の投稿IDと権限を確認したうえで、許可されていないユーザーにはarray('do_not_allow')を返します。user_has_capフィルターでedit_postのようなメタ権限を直接書き換える方法は実際の判定に影響しないため機能しません。Q特定の固定ページを管理画面の一覧から非表示にするには?
A
pre_get_postsフックで管理画面の固定ページ一覧クエリを修正し、除外したいIDをpost__not_inに追加します。current_user_can()でロール確認と組み合わせて権限のないユーザーにのみ適用します。Q投稿者ロールが自分の固定ページのみ編集できるようにするには?
A
map_meta_capフィルターでedit_pageケイパビリティをカスタマイズします。$post->post_authorと現在のユーザーIDが一致する場合のみ編集を許可するロジックを追加します。まとめ
- 特定ページ×特定ユーザー:
map_meta_capフィルターでdo_not_allowを返す - 全ページを許可:
user_has_capでプリミティブ権限(edit_pages等)を直接付与する - 注意:
edit_postのようなメタ権限を$allcapsに書き込んでも判定には使われない
投稿単位で細かく制御したいか、全体に権限を付与したいかに応じて、map_meta_capとuser_has_capを正しく使い分けてください。

