2026年5月25日

2026年5月25日

WordPressのカスタム管理画面ページにTablesorterでソート機能を追加する方法

WordPressの管理画面に自作したページの表を、見出しクリックで並べ替えられるようにするには、jQueryプラグインのTablesorterを自分のプラグイン内に同梱し、admin_enqueue_scripts でそのページにだけ読み込むのが手早い方法です。この記事では、管理メニューへのページ追加、表の出力(権限チェックとエスケープ込み)、Tablesorterの読み込みと初期化、数値や日付を正しく並べる工夫、データが多い場合の判断基準までを順に説明します。

なお、ここで扱うのはブラウザ側で並べ替える方式です。数千件を超えるデータや、ページ送りと組み合わせた並べ替えが必要なら、サーバー側で並べ替える WP_List_Table のほうが向いています。どちらを選ぶかの目安は後半で触れます。

Tablesorterについて先に知っておくこと

Tablesorterは、<table> の見出しをクリックすると行を並べ替えるjQueryプラグインです。元のプロジェクトのほかに、機能を大きく拡張したフォーク版(GitHubの Mottie/tablesorter)が広く使われており、この記事でもフォーク版を前提にします。フォーク版は2.31系が長く最新版で、近年は大きな更新が少ない状態です(2026年10月現在)。jQueryの将来のメジャーバージョンでの動作は保証されていないので、導入前にリポジトリの更新状況とissueを確認し、管理画面内の限られた用途で使うことをおすすめします。

WordPressのコアにはTablesorterは同梱されていません。jQuery本体はコアに含まれているので、依存関係として jquery を指定すれば読み込まれます。

手順1:プラグインを用意してファイルを配置する

テーマの functions.php に書くとテーマを切り替えたときに管理画面のページごと消えるため、管理用の機能は小さな独自プラグインにまとめます。構成は次のようにします。

wp-content/plugins/my-admin-report/
├── my-admin-report.php
└── assets/
    ├── jquery.tablesorter.min.js   (配布元から取得したファイル)
    └── admin-report.js

Tablesorterのファイルは外部CDNから直接読み込むこともできますが、管理画面で使うスクリプトは自サーバーに置くほうが、CDNの障害や改ざんの影響を受けません。取得したバージョン番号は控えておき、後で wp_register_script() のバージョン引数に使います。

手順2:管理ページと表を出力する

add_menu_page() は戻り値としてそのページの「フックサフィックス」を返します。これを変数に保存しておき、スクリプトの読み込み先を絞るのに使います。admin_menu は admin_enqueue_scripts より先に実行されるので、この順番で値を受け渡せます。

<?php
/**
 * Plugin Name: My Admin Report
 * Description: 投稿の一覧をソート可能な表で表示する管理ページ
 */

defined( 'ABSPATH' ) || exit;

add_action( 'admin_menu', function () {
	$hook = add_menu_page(
		'投稿レポート',
		'投稿レポート',
		'edit_others_posts',          // このページを見られる権限
		'my-admin-report',
		'my_admin_report_render',
		'dashicons-list-view',
		30
	);
	$GLOBALS['my_admin_report_hook'] = $hook; // admin_enqueue_scripts で比較に使う
} );

function my_admin_report_render() {
	if ( ! current_user_can( 'edit_others_posts' ) ) {
		wp_die( esc_html__( 'このページを表示する権限がありません。' ) );
	}

	$posts = get_posts( array(
		'post_type'      => 'post',
		'post_status'    => 'publish',
		'posts_per_page' => 300,
		'orderby'        => 'date',
		'order'          => 'DESC',
	) );
	?>
	<div class="wrap">
		<h1>投稿レポート</h1>
		<table id="my-report-table" class="widefat striped">
			<thead>
				<tr>
					<th>タイトル</th>
					<th>投稿者</th>
					<th>コメント数</th>
					<th>公開日</th>
					<th>操作</th>
				</tr>
			</thead>
			<tbody>
			<?php foreach ( $posts as $p ) : ?>
				<tr>
					<td><?php echo esc_html( get_the_title( $p ) ); ?></td>
					<td><?php echo esc_html( get_the_author_meta( 'display_name', $p->post_author ) ); ?></td>
					<td data-text="<?php echo esc_attr( (int) $p->comment_count ); ?>">
						<?php echo esc_html( number_format_i18n( $p->comment_count ) ); ?>
					</td>
					<td data-text="<?php echo esc_attr( get_post_time( 'U', true, $p ) ); ?>">
						<?php echo esc_html( get_the_date( '', $p ) ); ?>
					</td>
					<td><a href="<?php echo esc_url( get_edit_post_link( $p ) ); ?>">編集</a></td>
				</tr>
			<?php endforeach; ?>
			</tbody>
		</table>
	</div>
	<?php
}

ポイントは3つです。1つ目は、Tablesorterが <thead> と <tbody> を前提に動くことです。見出し行を <tbody> に入れると、見出しまで並べ替えの対象になります。2つ目は、class="widefat striped" を付けるとWordPress標準の表デザインになり、管理画面になじむことです。3つ目は、メニュー登録時の権限指定に加えて、表示関数の中でも current_user_can() で確認し、出力はすべて esc_html()・esc_attr()・esc_url() でエスケープしていることです。

data-text 属性は、並べ替えに使う値を表示とは別に持たせるためのものです。コメント数は 1,234 のような区切り付き、日付はサイトの日付形式で表示されるため、そのままでは文字列として並んでしまうことがあります。フォーク版のTablesorterは既定で data-text 属性の値を並べ替えに使うので、数値やUNIXタイムスタンプを入れておくと正しい順になります。

手順3:対象ページだけにスクリプトを読み込む

add_action( 'admin_enqueue_scripts', function ( $hook_suffix ) {
	if ( empty( $GLOBALS['my_admin_report_hook'] ) || $GLOBALS['my_admin_report_hook'] !== $hook_suffix ) {
		return; // 他の管理画面では読み込まない
	}

	$base = plugin_dir_url( __FILE__ ) . 'assets/';

	wp_register_script(
		'jquery-tablesorter',
		$base . 'jquery.tablesorter.min.js',
		array( 'jquery' ),
		'2.31.3', // 実際に同梱したバージョンに合わせる
		array( 'in_footer' => true )
	);

	wp_enqueue_script(
		'my-admin-report',
		$base . 'admin-report.js',
		array( 'jquery-tablesorter' ),
		'1.0.0',
		array( 'in_footer' => true )
	);

	wp_register_style( 'my-admin-report', false, array(), '1.0.0' );
	wp_enqueue_style( 'my-admin-report' );
	wp_add_inline_style( 'my-admin-report', '
		#my-report-table thead th { cursor: pointer; }
		#my-report-table .tablesorter-headerAsc::after { content: " \25B2"; }
		#my-report-table .tablesorter-headerDesc::after { content: " \25BC"; }
	' );
} );

すべての管理画面にスクリプトを読み込むと、他のプラグインの画面と衝突したり、管理画面全体が重くなったりします。フックサフィックスで絞るのはそのためです。サフィックスは toplevel_page_my-admin-report のような文字列になりますが、親メニューの種類によって変わるので、ハードコードせず add_menu_page() の戻り値を使うほうが安全です。

wp_register_script() の第5引数に配列(in_footer や strategy)を渡す形式はWordPress 6.3以降のものです。それより古い環境では true を渡します。

見出しの矢印に使っている tablesorter-headerAsc などのクラス名は、フォーク版が付与するものです。バージョンやテーマ設定で異なる場合があるので、ブラウザの開発者ツールで実際のクラス名を確認してから調整してください。

手順4:Tablesorterを初期化する

assets/admin-report.js に初期化処理を書きます。WordPressの管理画面ではjQueryがnoConflictモードで読み込まれるため、$ は使えません。jQuery(function ($) { ... }) の形で書くと、内側で $ を使えます。

jQuery(function ($) {
	var $table = $('#my-report-table');
	if (!$table.length || typeof $.fn.tablesorter !== 'function') {
		return;
	}

	$table.tablesorter({
		sortList: [[3, 1]],          // 4列目(公開日)を降順で初期表示
		headers: {
			4: { sorter: false }     // 5列目(操作)は並べ替えない
		}
	});
});

列の番号は0から数えます。sortList の [3, 1] は「4列目を降順」という意味で、0 なら昇順です。リンクだけの列のように並べ替える意味がない列は、headers で sorter: false を指定して対象から外します。

動かないときの確認ポイント

  • スクリプトが読み込まれていない: ページのソースか開発者ツールのNetworkタブで、jquery.tablesorter.min.js が読み込まれているか確認します。読み込まれていなければ、フックサフィックスの比較が一致していない可能性が高いです。error_log( $hook_suffix ); で実際の値を確認します。
  • **tablesorter is not a function のエラー**: 依存関係の指定漏れで、初期化スクリプトがTablesorterより先に実行されています。wp_enqueue_script() の依存配列を確認します。
  • 数値や日付の順序がおかしい: 表示用の文字列で並べ替えられています。data-text 属性に数値を入れ、HTMLに出力されているか確認します。
  • 見出しまで並べ替わる: 見出し行が <thead> の中にありません。

ブラウザ側ソートとWP_List_Tableの使い分け

Tablesorterは、表示済みのHTMLを並べ替えるだけなので、サーバーへの再問い合わせがなく反応が速いのが利点です。一方で、全件をHTMLとして出力する必要があるため、行数が増えるとページの読み込みが重くなります。目安として数百件程度まではTablesorterで十分ですが、それを超える場合や、検索・絞り込み・一括操作も必要な場合は、WordPress標準の投稿一覧と同じ仕組みの WP_List_Table を継承し、SQLの ORDER BY で並べ替えるほうが適しています。フォーク版には表の分割表示(pager)やフィルターのウィジェットもありますが、全件をブラウザに送る前提は変わりません。

ダッシュボードのウィジェット内の表に適用したい場合は、wp_add_dashboard_widget() で出力した表に同じ初期化を行い、admin_enqueue_scripts の比較対象をダッシュボードのフックサフィックスである index.php にします。

まとめ

  • Tablesorterは独自プラグインに同梱し、add_menu_page() の戻り値で対象ページだけに読み込む
  • 表は <thead>・<tbody> で組み、権限チェックとエスケープを行って出力する
  • 数値や日付は data-text 属性に並べ替え用の値を持たせる
  • 管理画面では jQuery(function ($) { ... }) で初期化し、操作列などは sorter: false で外す
  • データが多い・検索や一括操作も必要なら WP_List_Table を検討する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲