この記事の対象: WordPressサイトを制作・納品する制作者。functions.php を編集できる人
読了時間: 約15分
納品後に届く連絡でいちばん多いのが「触っていたら表示がおかしくなった」です。原因を追うと、テーマエディターでCSSを直接書き換えていた、固定ページのテンプレート選択を変えていた、使わないプラグインを有効化していた——このあたりに集中します。
クライアントは壊そうとして触っていません。管理画面に並んでいるから、触れるものだと判断しただけです。だとすれば対策は教育ではなく実装側にあります。使わないメニューを消し、投稿画面の項目を絞り、ダッシュボードに使い方を出す。この記事では、その3つをコピーしてそのまま動くコードで進めます。
前提と作業環境の確認

対象となるWordPress環境
この記事のコードは以下を前提にしています。
| 項目 | 前提 |
|---|---|
| WordPress | 6.0以降 |
| PHP | 8.0以降 |
| テーマ | クラシックテーマ/ブロックテーマの両方(差がある箇所は明記します) |
| 編集するファイル | 子テーマの functions.php、またはサイト固有プラグイン |
| 必要な権限 | 管理者(administrator)でのログイン |
親テーマの functions.php を直接書き換えると、テーマ更新で消えます。有料テーマを使っている場合はとくに危険なので、子テーマを作るかサイト固有プラグインにまとめてください。テーマの選定段階から考えたい場合はこちらが参考になります。
なお、この記事で扱うフックやスラッグはWordPressのバージョンによって変わる可能性があります。実装前に自分の環境で挙動を確認してください。確認用のコードは後述します。
置き場所は2択
コードの置き場所は次のどちらかにします。
子テーマの functions.php
wp-content/themes/【子テーマ名】/functions.php
サイト固有プラグイン(推奨)
wp-content/plugins/site-admin-cleanup/site-admin-cleanup.php
プラグインにする場合、ファイルの先頭に次のヘッダーコメントが必要です。これがないとWordPressがプラグインとして認識しません。
<?php
/**
* Plugin Name: Site Admin Cleanup
* Description: 納品先向けに管理画面を整理する
* Version: 1.0.0
* Author: 【自分の名前または屋号】
*/
// 直接アクセスを防ぐ
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
以降のコードは、すべてこのファイルの下に続けて貼れる形で書いています。
変更する箇所: Author: を自分の名前に。Plugin Name は管理画面のプラグイン一覧に出るので、クライアントが見て意味がわかる日本語にしてもかまいません。
プラグイン方式を推す理由は3つあります。テーマを入れ替えても設定が残ること、「この整理を一時的に外す」がプラグインの停止だけでできること、そしてファイル名でGit管理しやすいことです。トラブル切り分けのとき、2つ目の差がとくに効きます。テーマの functions.php に書いていると、切り分けのたびにコードをコメントアウトして戻す作業が発生します。
作業前にやっておくこと
管理画面をいじるコードは、書き間違えると管理画面自体が開かなくなります。FTPかSSHでファイルを戻せる状態を必ず作ってから始めてください。
上から順に進めます。順序を変えると、権限を決める前にメニューを消してしまい「誰に対して消したのか」が曖昧になります。
もう1つ、作業前に用意しておくと後が楽なのが確認用の編集者アカウントです。この記事のコードはすべて管理者を除外する分岐が入っているので、管理者のまま画面を開いても何も変わりません。ユーザー → 新規追加で権限「編集者」のアカウントを1つ作り、シークレットウィンドウでログインして確認します。納品時にはそのアカウントをそのままクライアントに渡すか、削除するかを決めてください。
バックアップ体制そのものを整えたい場合は、こちらでツール構成を扱っています。
クライアントの権限を先に決める

管理者を渡すか、編集者に留めるか
メニューを隠す前に決めるべきことがあります。クライアントのアカウントを管理者にするかどうかです。
編集者(editor)で渡す
- プラグイン・テーマの画面が最初から出ない
- ユーザー管理ができない
- 更新の通知が出ない
- 保守契約とセットにしやすい
管理者(administrator)で渡す
- コードで隠す作業が増える
- 隠しても直URLで到達できる
- 自分でプラグインを入れられる
- 契約終了後も自走できる
編集者で渡せるなら、そのほうが安全です。プラグイン画面もテーマ画面も権限の段階で存在しないので、隠す作業がほぼ不要になります。
ただし現実には管理者を求められることが多いです。保守契約がない、将来別の会社に引き継ぐ、社内に詳しい人がいる——このどれかなら管理者で渡すことになります。その場合は「隠す」実装が本題になります。
判断に迷ったら、契約書に更新作業の担当が書かれているかを見てください。制作者側が更新を請け負うと明記されているなら編集者で足ります。書かれていない、もしくは「クライアント側で運用」となっているなら管理者を渡す前提で設計します。権限の設計は契約の写しであるべきで、技術的な好みで決める場所ではありません。
隠すことの限界を理解しておく
先に釘を刺しておきます。メニューを隠しても、URLを直接叩けばその画面は開きます。
remove_menu_page() は管理メニューの表示を消すだけで、権限を変えません。/wp-admin/theme-editor.php とブラウザに打てば、テーマエディターは普通に開きます。
つまり隠す実装の目的は「悪意ある操作を防ぐ」ことではなく、誤操作の入口をなくすことです。悪意や強い意志のある操作を止めるには、権限そのものを削るか、機能を無効化する必要があります。この記事では後半で両方を扱います。
使わない管理メニューを消す

メニューの構造を把握する
WordPressの管理メニューは、親メニューと子メニュー(サブメニュー)の2階層です。
外観(themes.php)
- テーマ
- カスタマイズ
- ウィジェット
- メニュー
- テーマファイルエディター
ツール(tools.php)
- 利用可能なツール
- インポート
- エクスポート
- サイトヘルス
コメント(edit-comments.php)
親メニューを消すと子メニューも一緒に消えます。「外観のメニュー編集だけは触らせたい、テーマエディターは消したい」というときは、親を残して子だけ消します。
親メニューを消すコード
そのまま貼れる形です。
/**
* 管理者以外に見せない親メニューを消す
*/
add_action( 'admin_menu', 'sac_remove_parent_menus', 999 );
function sac_remove_parent_menus() {
// 管理者には全部見せる
if ( current_user_can( 'manage_options' ) ) {
return;
}
$targets = array(
'edit-comments.php', // コメント
'tools.php', // ツール
'edit.php?post_type=page', // 固定ページ
);
foreach ( $targets as $slug ) {
remove_menu_page( $slug );
}
}
変更する箇所: $targets の中身です。そのサイトで使わないものだけを残してください。固定ページを触らせたいなら edit.php?post_type=page の行を消します。
主要なスラッグの一覧を置きます。
| メニュー | スラッグ |
|---|---|
| ダッシュボード | index.php |
| 投稿 | edit.php |
| メディア | upload.php |
| 固定ページ | edit.php?post_type=page |
| コメント | edit-comments.php |
| 外観 | themes.php |
| プラグイン | plugins.php |
| ユーザー | users.php |
| ツール | tools.php |
| 設定 | options-general.php |
カスタム投稿タイプは edit.php?post_type=【投稿タイプ名】 の形になります。プラグインが追加したメニューは独自のスラッグを持つので、後述の確認用コードで実物を読んでください。
子メニューだけを消すコード
親は残して、中の一部だけ消す場合です。
/**
* 子メニューを個別に消す
*/
add_action( 'admin_menu', 'sac_remove_sub_menus', 999 );
function sac_remove_sub_menus() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
// array( 親スラッグ, 子スラッグ )
$targets = array(
array( 'themes.php', 'theme-editor.php' ), // テーマファイルエディター
array( 'themes.php', 'widgets.php' ), // ウィジェット
array( 'themes.php', 'themes.php' ), // テーマ一覧
array( 'plugins.php', 'plugin-editor.php' ), // プラグインファイルエディター
array( 'options-general.php', 'options-permalink.php' ), // パーマリンク設定
);
foreach ( $targets as $t ) {
remove_submenu_page( $t[0], $t[1] );
}
}
変更する箇所: 同じく $targets です。テーマの構成によって不要な項目は変わります。
パーマリンク設定を隠すのは実務上かなり効きます。ここを変えると全ページのURLが変わり、外部からのリンクも検索エンジンの評価も切れます。クライアントが「なんとなくきれいにしよう」と触るとサイトごと巻き添えになる場所です。しかも変えた本人に自覚がないので、連絡が来るのは「なぜかGoogleから消えた」という形になり、原因にたどり着くまでに時間がかかります。
ブロックテーマの場合の注意点
ブロックテーマ(theme.json を持ち、サイトエディターに対応したテーマ)では、外観メニューの中身が変わります。テーマエディターやウィジェットの代わりに「エディター」(サイトエディター)が入ります。
サイトエディターを消すコードです。
/**
* ブロックテーマのサイトエディターを消す
*/
add_action( 'admin_menu', 'sac_remove_site_editor', 999 );
function sac_remove_site_editor() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
remove_submenu_page( 'themes.php', 'site-editor.php' );
}
サイトエディターはヘッダー・フッターを含むサイト全体のテンプレートを編集できます。クラシックテーマのウィジェット編集より影響範囲が広く、ヘッダーのブロックをうっかり削除すると全ページからナビゲーションが消えます。ブロックテーマで納品するなら、ここは優先して塞ぐ場所です。
自分のサイトが実際にどのスラッグを持っているかは、次のコードで確認できます。開発中だけ有効にして、確認したら消してください。
/**
* 【確認用・本番では消す】管理メニューのスラッグを画面に出す
*/
add_action( 'admin_notices', 'sac_debug_menu_slugs' );
function sac_debug_menu_slugs() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
global $menu, $submenu;
echo '<div class="notice notice-info"><pre style="max-height:400px;overflow:auto;">';
foreach ( $menu as $m ) {
if ( empty( $m[0] ) ) {
continue;
}
echo esc_html( wp_strip_all_tags( $m[0] ) . ' => ' . $m[2] ) . "\n";
if ( ! empty( $submenu[ $m[2] ] ) ) {
foreach ( $submenu[ $m[2] ] as $s ) {
echo ' ' . esc_html( wp_strip_all_tags( $s[0] ) . ' => ' . $s[2] ) . "\n";
}
}
}
echo '</pre></div>';
}
これを入れて管理画面を開くと、実際のスラッグが全部出ます。テーマやプラグインが独自に追加したメニューのスラッグもここで拾えるので、当て推量で書くよりずっと速く終わります。
ファイルエディターは機能ごと止める
テーマエディターとプラグインエディターは、隠すだけでは足りません。ここでコードを壊されると、サイト全体が白画面になります。機能そのものを止めます。
置き場所は wp-config.php です。/* That's all, stop editing! */ の行より上に書きます。
define( 'DISALLOW_FILE_EDIT', true );
これを入れると、管理画面からのファイル編集機能が完全に無効になります。メニューも自動的に消えます。URLを直接叩いても「ファイルを編集する権限がありません」で止まります。
制作者側も管理画面からコードを触れなくなりますが、そもそもFTPかGitで触るべきなので実務上の支障はありません。納品サイトには基本的に入れておく設定です。
プラグインの新規インストールと更新も止めたい場合は次を追加します。
define( 'DISALLOW_FILE_MODS', true );
こちらは保守契約の形によって判断が分かれます。制作者側が更新を請け負う契約なら入れる、クライアントが自分で更新する契約なら入れない。契約の中身と揃えるのが正解で、技術的にどちらが良いという話ではありません。
なお DISALLOW_FILE_MODS はWordPress本体の自動更新も止めます。セキュリティリリースが自動で当たらなくなるので、入れるなら更新を誰がいつやるかを保守メニューに明記してからにしてください。入れたまま放置するのがいちばん危険な状態です。
保守の範囲をどう切るかはこちらで整理しています。
管理バーとダッシュボードを整理する

上部の管理バーを削る
画面上部の黒いバーにも、使わない項目が並んでいます。特に「カスタマイズ」はテーマ設定に直行するので、消しておく価値があります。
/**
* 管理バーの項目を消す
*/
add_action( 'admin_bar_menu', 'sac_remove_admin_bar_items', 999 );
function sac_remove_admin_bar_items( $wp_admin_bar ) {
if ( current_user_can( 'manage_options' ) ) {
return;
}
$targets = array(
'wp-logo', // WordPressロゴ(フォーラムやドキュメントへのリンク)
'customize', // カスタマイズ
'comments', // コメント
'new-content', // 新規追加
'updates', // 更新通知
);
foreach ( $targets as $id ) {
$wp_admin_bar->remove_node( $id );
}
}
変更する箇所: $targets。new-content を消すと「+新規」のドロップダウンごと消えるので、投稿を書いてもらう運用なら残します。
管理バーはフロント側にも出ます。ログイン状態でサイトを見ているクライアントは、記事ページから直接「編集」に入る動線を使うことが多いので、ここを消しすぎると逆に不便になります。消すのは設定系(customize・updates)に留めるのが無難です。
ダッシュボードのウィジェットを消す
初期状態のダッシュボードには「WordPressイベントとニュース」「アクティビティ」「クイックドラフト」などが並んでいます。クライアントにとって意味のある情報はほぼないので、片付けます。
/**
* ダッシュボードの初期ウィジェットを消す
*/
add_action( 'wp_dashboard_setup', 'sac_remove_dashboard_widgets' );
function sac_remove_dashboard_widgets() {
remove_meta_box( 'dashboard_primary', 'dashboard', 'side' ); // WordPressイベントとニュース
remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' ); // クイックドラフト
remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' ); // アクティビティ
remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' ); // 概要
remove_meta_box( 'dashboard_site_health', 'dashboard', 'normal' ); // サイトヘルスステータス
}
変更する箇所: 消したくないものの行を削除するだけです。「概要」は投稿数が見えるので残す判断もあります。
サイトヘルスは制作者には有用ですが、クライアントが見ると「重大な問題があります」の赤字だけを読んで不安になります。連絡が増えるだけなので消しておくほうが親切です。
プラグインが独自に追加したダッシュボードウィジェット(SEO系・アクセス解析系に多い)は、上のコードでは消えません。IDが違うためです。実際のIDは、ダッシュボードでそのウィジェットを検証し、外側の <div id="..."> を読むと分かります。そのIDを remove_meta_box() の第1引数に足してください。第2引数は 'dashboard'、第3引数はそのウィジェットが表示されている側(左なら 'normal'、右なら 'side')です。
使い方の案内をダッシュボードに置く
ここが本題です。空いたダッシュボードに、そのサイト専用の案内を出します。
/**
* ダッシュボードに使い方の案内を追加する
*/
add_action( 'wp_dashboard_setup', 'sac_add_guide_widget' );
function sac_add_guide_widget() {
wp_add_dashboard_widget(
'sac_guide',
'このサイトの更新方法',
'sac_render_guide_widget'
);
// 一番上に移動させる
global $wp_meta_boxes;
$normal = $wp_meta_boxes['dashboard']['normal']['core'];
$guide = array( 'sac_guide' => $normal['sac_guide'] );
unset( $normal['sac_guide'] );
$wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $guide, $normal );
}
function sac_render_guide_widget() {
?>
<style>
.sac-guide h4 { margin: 1em 0 .4em; font-size: 14px; }
.sac-guide ol { margin: 0 0 1em 1.6em; }
.sac-guide li { margin-bottom: .3em; }
.sac-guide .sac-warn {
background: #fcf3d6;
border-left: 4px solid #dba617;
padding: .8em 1em;
margin: 1em 0 0;
}
</style>
<div class="sac-guide">
<h4>お知らせを追加する</h4>
<ol>
<li>左メニューの<strong>「投稿」→「新規追加」</strong>を開きます</li>
<li>タイトルと本文を入れます</li>
<li>右上の<strong>「公開」</strong>を押すと、トップページの一覧に出ます</li>
</ol>
<h4>画像を差し替える</h4>
<ol>
<li>左メニューの<strong>「固定ページ」</strong>から対象のページを開きます</li>
<li>画像をクリックして<strong>「置換」</strong>を選びます</li>
<li><strong>「更新」</strong>を押します</li>
</ol>
<div class="sac-warn">
<strong>ご相談ください</strong><br>
ページを新しく作りたいとき、レイアウトを変えたいときは
<a href="mailto:【連絡先メールアドレス】">【連絡先メールアドレス】</a>
までご連絡ください。
</div>
</div>
<?php
}
変更する箇所:
- ウィジェットのタイトル「このサイトの更新方法」
- 各手順の文言。そのサイトの実際の構成に合わせて書き換える
【連絡先メールアドレス】を2箇所.sac-warnの色(#fcf3d6と#dba617)は変えなくても管理画面に馴染みます
手順を書くときのコツは、メニュー名を実際の表示どおりに書くことです。「投稿一覧から」ではなく「左メニューの『投稿』→『新規追加』」と書きます。クライアントは画面上の文字と説明の文字を照合しながら操作するので、言い換えると迷います。
もう1つ、「やってはいけないこと」を書かないのもコツです。禁止事項を並べると、書いていないことは全部やっていいという読み方になります。やってほしい操作だけを手順で示し、それ以外は「ご相談ください」に集約するほうが、結果として問い合わせも操作事故も減ります。
<style> をウィジェット内に直接書いているのは、この案内だけのためにCSSファイルを1本読み込ませたくないからです。管理画面のロードにも表示速度の話は効きます。
投稿・固定ページの編集画面を絞る

不要なメタボックスを外す
投稿画面にも使わない項目が並びます。カスタムフィールド、抜粋、トラックバック、リビジョンなど。
/**
* 投稿画面のメタボックスを外す
*/
add_action( 'admin_menu', 'sac_remove_post_meta_boxes' );
function sac_remove_post_meta_boxes() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
// 投稿
remove_meta_box( 'trackbacksdiv', 'post', 'normal' ); // トラックバック
remove_meta_box( 'postcustom', 'post', 'normal' ); // カスタムフィールド
remove_meta_box( 'commentstatusdiv', 'post', 'normal' );// ディスカッション
remove_meta_box( 'commentsdiv', 'post', 'normal' ); // コメント
remove_meta_box( 'postexcerpt', 'post', 'normal' ); // 抜粋
remove_meta_box( 'slugdiv', 'post', 'normal' ); // スラッグ
// 固定ページ
remove_meta_box( 'trackbacksdiv', 'page', 'normal' );
remove_meta_box( 'postcustom', 'page', 'normal' );
remove_meta_box( 'commentstatusdiv', 'page', 'normal' );
remove_meta_box( 'pageparentdiv', 'page', 'side' ); // ページ属性(親ページ・テンプレート)
}
変更する箇所: サイトの設計次第です。抜粋をテーマで使っているなら postexcerpt の行は消してください。
pageparentdiv を外す判断は分かれます。ここには親ページの指定とテンプレート選択が入っています。テンプレートを切り替えられると意図しないレイアウトになるので、固定ページの構成が完成しているサイトでは外す価値があります。逆に、クライアントが自分でページを増やす運用なら残さないと困ります。
カスタムフィールドを ACF(Advanced Custom Fields)などのプラグインで組んでいる場合、postcustom(標準のカスタムフィールド欄)を外してもプラグイン側のフィールドは残ります。標準欄は生のキーと値がそのまま並んで見えるだけなので、クライアントに見せる意味はありません。ACFを使っている案件ほど外しておく価値があります。
ブロックエディターでは別の指定が必要
ここが引っかかりやすい点です。ブロックエディター(Gutenberg)では remove_meta_box() が効かない項目があります。
抜粋、ディスカッション、スラッグなどは、ブロックエディターでは右サイドバーのパネルとして描画されます。これはPHPのメタボックスではなくJavaScript側の実装なので、remove_meta_box() の対象外です。
対処法は2つあります。
方法1: 投稿タイプのサポートを外す
抜粋そのものを使わないなら、投稿タイプの機能を外すのが確実です。
/**
* 投稿タイプのサポートを外す
*/
add_action( 'init', 'sac_remove_post_type_support' );
function sac_remove_post_type_support() {
remove_post_type_support( 'post', 'excerpt' ); // 抜粋
remove_post_type_support( 'post', 'trackbacks' ); // トラックバック
remove_post_type_support( 'post', 'custom-fields' ); // カスタムフィールド
remove_post_type_support( 'page', 'comments' ); // コメント
remove_post_type_support( 'page', 'custom-fields' );
}
これはブロックエディターでもクラシックエディターでも効きます。ただしテーマ側で the_excerpt() を使っている場合、抜粋を外すと本文からの自動生成に切り替わるので、表示を確認してください。
このコードは init フックに掛けます。カスタム投稿タイプを対象にするときは、その投稿タイプが登録された後に実行される必要があるので、優先度を上げて add_action( 'init', '関数名', 99 ) にしておくと確実です。
方法2: CSSでパネルを隠す
サポートは残したいが編集させたくない、という場合はCSSで隠します。管理画面用のスタイルをフックで追加します。
/**
* 管理画面のブロックエディターのパネルをCSSで隠す
*/
add_action( 'admin_head', 'sac_hide_editor_panels' );
function sac_hide_editor_panels() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
$screen = get_current_screen();
if ( ! $screen || 'post' !== $screen->base ) {
return;
}
?>
<style>
/* パーマリンク(スラッグ) */
.editor-post-panel__row.editor-post-url,
.edit-post-post-link { display: none !important; }
/* ディスカッション */
.editor-post-discussion,
.edit-post-post-discussion { display: none !important; }
</style>
<?php
}
変更する箇所: セレクタです。ここは注意が必要で、ブロックエディターのクラス名はWordPressのバージョンで変わります。 上のコードは新旧2つのクラス名を並べていますが、これで確実という保証はありません。
自分の環境で確認する手順です。
- 投稿の編集画面を開く
- 隠したいパネルを右クリックして「検証」
- その要素の親をたどって、パネル全体を囲むクラスを探す
- そのクラス名をコードに追加する
このとき、editor- で始まるクラスを優先して拾ってください。 edit-post- で始まるものは古い世代の名前で、将来消える可能性があります。両方書いておけば当面はどちらでも当たります。
CSSで隠す方法は保守コストが乗ります。WordPressを更新したら効かなくなっている可能性があるので、更新後に管理画面を確認する運用が前提です。可能なら方法1を選んでください。
投稿一覧の列を整理する
一覧画面の列も削れます。コメント数の列など、使わないものが並んでいます。
/**
* 投稿一覧の列を減らす
*/
add_filter( 'manage_posts_columns', 'sac_filter_post_columns' );
add_filter( 'manage_pages_columns', 'sac_filter_post_columns' );
function sac_filter_post_columns( $columns ) {
if ( current_user_can( 'manage_options' ) ) {
return $columns;
}
unset( $columns['comments'] ); // コメント数
unset( $columns['author'] ); // 投稿者
unset( $columns['tags'] ); // タグ
return $columns;
}
変更する箇所: unset() する列のキーです。運用者が1人なら投稿者列は不要ですが、複数人で更新するサイトなら残します。
列を減らすと、狭い画面でもタイトルの表示幅が広がります。クライアントは記事タイトルで目的の記事を探すので、ここが切れないだけで一覧の使い勝手が変わります。
クライアントに伝わる形に仕上げる

管理画面のフッターとログイン画面
細かいところですが、印象が変わります。管理画面下部の「WordPressのご利用ありがとうございます」を、連絡先に差し替えます。
/**
* 管理画面フッターのテキストを差し替える
*/
add_filter( 'admin_footer_text', 'sac_admin_footer_text' );
function sac_admin_footer_text() {
return 'サイトのお困りごとは <a href="mailto:【連絡先メールアドレス】">【連絡先メールアドレス】</a> まで';
}
/**
* 管理画面右下のバージョン表記を消す
*/
add_filter( 'update_footer', 'sac_remove_version_footer', 11 );
function sac_remove_version_footer() {
return '';
}
変更する箇所: 【連絡先メールアドレス】 を2箇所。
フッターは全画面の下部に出るので、連絡先の置き場所として効率がいい場所です。ダッシュボードの案内ウィジェットはダッシュボードにしか出ませんが、フッターは投稿編集中でも見えます。「どこに連絡すればいいか分からない」で止まる時間がなくなります。
バージョン表記を消すのは、セキュリティ上の意味もあります。ただしこれはページのソースからも読める情報なので、これだけで守りが固まるわけではありません。表示を整える目的が主です。
更新通知をクライアントに見せない
保守契約で更新を請け負っている場合、更新通知はクライアントには不要です。見えると「押していいのか」と迷わせるだけです。
/**
* 管理者以外に更新通知を見せない
*/
add_action( 'admin_init', 'sac_hide_update_notices' );
function sac_hide_update_notices() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
remove_action( 'admin_notices', 'update_nag', 3 );
remove_action( 'network_admin_notices', 'update_nag', 3 );
}
逆に、クライアント自身が更新する契約なら入れないでください。通知が出ないまま古いバージョンで放置されるのが、いちばん困る状態です。
権限で絞る形に置き換える
ここまでのコードは current_user_can( 'manage_options' ) で分岐しています。この判定に頼らず、権限そのものを削る方法もあります。
/**
* 編集者からテーマ切り替え権限を外す(1回だけ実行して消す)
*/
add_action( 'admin_init', 'sac_adjust_editor_caps' );
function sac_adjust_editor_caps() {
$role = get_role( 'editor' );
if ( ! $role ) {
return;
}
$role->remove_cap( 'switch_themes' );
$role->remove_cap( 'edit_theme_options' );
}
重要: add_role() や remove_cap() はデータベースに書き込まれます。一度実行すれば設定が残るので、確認後はこのコードを消してかまいません。逆に、消したあとで元に戻したいときは add_cap() で戻す必要があります。コードを消すだけでは戻りません。
権限を削るほうが、URLを直接叩かれても止まる点で強い実装です。ただし戻すのが面倒なので、案件ごとに必要かどうか判断してください。
引き継ぎのことも考えておいてください。権限をコードで削っていると、次に入る制作会社が「なぜこの編集者はテーマを切り替えられないのか」を調べるところから始まります。データベースに残る変更を加えたときは、その事実を納品ドキュメントに1行書いておくのが実務上の作法です。コードを消してしまうと、ソースを読んでも理由が分かりません。
全部まとめた最小構成
実務でよく使う組み合わせを1つにまとめます。これをコピーして、不要な行を削る使い方を想定しています。
<?php
/**
* Plugin Name: Site Admin Cleanup
* Description: 納品先向けに管理画面を整理する
* Version: 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// 1. 管理者以外にメニューを見せない
add_action( 'admin_menu', 'sac_cleanup_menus', 999 );
function sac_cleanup_menus() {
if ( current_user_can( 'manage_options' ) ) {
return;
}
remove_menu_page( 'edit-comments.php' );
remove_menu_page( 'tools.php' );
remove_submenu_page( 'themes.php', 'theme-editor.php' );
remove_submenu_page( 'themes.php', 'widgets.php' );
remove_submenu_page( 'options-general.php', 'options-permalink.php' );
}
// 2. ダッシュボードを片付ける
add_action( 'wp_dashboard_setup', 'sac_cleanup_dashboard' );
function sac_cleanup_dashboard() {
remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' );
remove_meta_box( 'dashboard_site_health', 'dashboard', 'normal' );
}
// 3. 投稿タイプのサポートを外す
add_action( 'init', 'sac_cleanup_supports' );
function sac_cleanup_supports() {
remove_post_type_support( 'post', 'trackbacks' );
remove_post_type_support( 'post', 'custom-fields' );
remove_post_type_support( 'page', 'comments' );
remove_post_type_support( 'page', 'custom-fields' );
}
// 4. 管理バーを削る
add_action( 'admin_bar_menu', 'sac_cleanup_admin_bar', 999 );
function sac_cleanup_admin_bar( $bar ) {
if ( current_user_can( 'manage_options' ) ) {
return;
}
$bar->remove_node( 'wp-logo' );
$bar->remove_node( 'customize' );
$bar->remove_node( 'comments' );
}
// 5. フッターを差し替える
add_filter( 'admin_footer_text', function () {
return 'サイトのお困りごとは <a href="mailto:【連絡先】">【連絡先】</a> まで';
} );
add_filter( 'update_footer', function () {
return '';
}, 11 );
変更する箇所: 関数名の接頭辞 sac_ を自分のものに変える(他のプラグインと衝突を避けるため)、【連絡先】 を2箇所、そして各リストの中身。
ダッシュボードの案内ウィジェットは案件ごとに文言が変わるので、この最小構成には入れていません。前のセクションのコードを足してください。
wp-config.php の DISALLOW_FILE_EDIT はこのファイルには入れられません。定数の定義はWordPressの読み込み順の都合で wp-config.php に置く必要があります。プラグインを入れるときにセットで書く手順として覚えておいてください。
うまくいかないとき

管理画面が真っ白になった
PHPの構文エラーです。FTPかSSHで該当ファイルを開き、直前に追加したコードを消してください。プラグイン方式なら、wp-content/plugins/site-admin-cleanup/ のフォルダ名を変えるだけで無効化できます。
エラーの内容を見たいときは wp-config.php に次を入れます。
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
wp-content/debug.log にエラーが出ます。本番サイトでは確認後に必ず消してください。 ログファイルが外部から読めてしまう構成もあります。
remove_menu_page() が効かない
3つの原因が考えられます。
優先度が足りない
プラグインが admin_menu にメニューを追加するタイミングより先に消そうとしています。add_action の第3引数を 999 にしてください。それでも効かなければ 9999 まで上げます。
スラッグが違う
とくにプラグインが追加したメニューは、想像と違うスラッグを持っています。この記事の「確認用」コードを入れて実際のスラッグを確認してください。
自分が管理者のまま確認している
いちばん多い原因です。コードに current_user_can( 'manage_options' ) の分岐が入っているので、管理者のあなたには何も起きません。確認は編集者アカウントを作り、シークレットウィンドウでログインして行ってください。
remove_meta_box() が効かない
ブロックエディターのパネルです。前述のとおり remove_post_type_support() かCSSに切り替えてください。
クラシックエディターでも効かない場合は、フックのタイミングが原因です。admin_menu ではなく add_meta_boxes を使い、優先度を高くします。
add_action( 'add_meta_boxes', 'sac_remove_late_meta_boxes', 999 );
function sac_remove_late_meta_boxes() {
remove_meta_box( '【メタボックスのID】', 'post', 'normal' );
}
変更する箇所: 【メタボックスのID】。IDは編集画面で該当ボックスを検証し、<div id="..."> の値を読めばわかります。
第3引数(normal / side / advanced)が実際の表示位置と違うと消えません。左側に出ているなら normal、右側なら side です。ドラッグで位置を動かしたことがある場合は表示と初期値がずれていることがあるので、advanced も試してください。
CSSで隠したパネルが更新後に戻った
ブロックエディターのクラス名が変わったためです。同じ手順でクラス名を再取得して追加してください。
このリスクがあるので、CSSで隠す箇所は最小限にとどめ、可能なものは remove_post_type_support() に寄せるのが安全です。WordPressの更新後に管理画面を一通り開いて確認する作業を、保守メニューに入れておくと安心できます。確認するのは、投稿の新規追加・固定ページの編集・ダッシュボードの3画面で足ります。
隠した機能をクライアントが直URLで開いた
隠すだけでは止まりません。本当に触らせたくない機能は、次のどれかで対処します。
| やりたいこと | 手段 |
|---|---|
| ファイル編集を止める | wp-config.php に DISALLOW_FILE_EDIT |
| プラグイン導入を止める | wp-config.php に DISALLOW_FILE_MODS |
| テーマ切り替えを止める | remove_cap( 'switch_themes' ) |
| そもそも権限を渡さない | 編集者アカウントで納品する |
納品後にクライアントから「メニューが足りない」と言われた
隠しすぎたときの話です。この記事の構成なら、プラグイン方式にしておけば $targets の配列から1行消して差し替えるだけで戻ります。
その場で戻す前に、何をしたくてその画面を探していたのかを聞いてください。 「メディアを整理したい」「投稿者名を変えたい」といった目的が分かれば、その画面を開放するのではなく、ダッシュボードの案内に手順を1つ足すほうが良い場合があります。開けた画面は次に別の事故を生みます。
サーバー環境で挙動が違う
管理画面のカスタマイズ自体はサーバーに依存しませんが、wp-config.php の編集やFTPでの復旧経路はサーバーによって手順が変わります。復旧できない環境で本番を触るのは避けてください。
よくある質問

プラグインで管理画面を整理するのと、コードで書くのはどちらがいいですか
納品先のサイトではコードのほうが管理しやすいです。プラグインは設定がデータベースに入るため、環境を移したときに再設定が必要になったり、クライアントがプラグインを停止して元に戻ってしまったりします。この記事の内容は数十行で済むので、サイト固有プラグインとしてファイルで持つほうが確実です。
メニューを隠しても直接URLを打てば開くなら、隠す意味はありますか
あります。納品後のトラブルの多くは「見えたから触った」という誤操作で、悪意ある操作ではありません。入口を消せばその大半が起きなくなります。そのうえで、本当に触られると困る機能だけ DISALLOW_FILE_EDIT や権限の削除で塞ぐのが現実的な組み合わせです。
クライアントには管理者権限を渡すべきですか
保守契約があり、更新も制作者側が請け負うなら編集者で足ります。将来別の会社に引き継ぐ可能性がある、社内にWordPressを扱える人がいる、という場合は管理者で渡してこの記事のコードで整理します。どちらにしても、権限の設計を先に決めてからメニューを削ってください。
ブロックテーマとクラシックテーマでコードは変わりますか
大半は共通で動きます。違いが出るのは外観メニューの中身(ブロックテーマではサイトエディターが入る)と、投稿画面の右サイドバーのパネル(ブロックエディターでは remove_meta_box() が効かないものがある)の2箇所です。この記事ではそれぞれ別の対処法を書いているので、自分のテーマがどちらかを先に確認してください。
管理画面を整理したら、クライアントへの説明も必要ですか
必要です。整理したうえで、ダッシュボードに「このサイトの更新方法」を置き、そこに書いた範囲だけ触ってもらう形にします。納品時の説明とダッシュボードの案内が同じ内容になっていると、クライアントは後から画面を見て思い出せます。口頭説明だけだと忘れられます。
まとめ
納品先の管理画面を整理する作業は、次の順で進めます。
| 順番 | やること | 主な手段 |
|---|---|---|
| 1 | 復旧経路を確保する | FTP/SSHの接続確認 |
| 2 | 権限を決める | 編集者か管理者か |
| 3 | メニューを削る | remove_menu_page() / remove_submenu_page() |
| 4 | ファイル編集を止める | DISALLOW_FILE_EDIT |
| 5 | 投稿画面を絞る | remove_post_type_support() / remove_meta_box() |
| 6 | 案内を出す | wp_add_dashboard_widget() |
コードは数十行ですが、効果は納品後の問い合わせ件数に直接出ます。とくに「パーマリンク設定を隠す」「ファイルエディターを止める」の2つは、壊れたときの復旧コストが大きい場所なので優先度が高いです。
ダッシュボードの案内は、テンプレートを1つ持っておくと毎回の作業が短時間で終わります。案件ごとに変わるのはメニュー名と連絡先だけなので、そこを差し替える形で運用してください。1案件ぶん書いたら、そのファイルを次の案件の起点にします。
最後に1つ。この整理は納品直前ではなく、テスト段階でやってください。 隠した状態で自分が一通り更新作業をしてみると、「この画面が無いと運用できない」が必ず1つか2つ出ます。それを納品後にクライアントから指摘されるより、自分で見つけるほうが早く済みます。
CMSの選定段階から悩んでいる場合は、こちらも合わせて読んでください。





