2026年9月12日
2026年9月12日
WordPressのページネーションが動作しない問題を解決する方法
はじめに
WordPressのブログ一覧や検索結果ページで「次のページ」をクリックすると404エラーが表示される・URLが/page/2/に変わっても1ページ目と同じ内容が表示される・the_posts_pagination()を使っているのにページネーションが表示されない・WP_Queryでカスタムクエリを作成したがページネーションが機能しないといった問題は、パーマリンク設定・pagedパラメーターの設定ミス・$wp_queryの上書き・max_num_pagesの未設定が原因です。
症状・原因
- パーマリンク設定が「基本」になっていて
/page/2/形式のURLが機能しない - カスタム
WP_Queryでpagedパラメーターを正しく渡していない query_posts()を使用してメインクエリを上書きしているためmax_num_pagesが壊れている- 固定ページをフロントページに設定している場合の
pagedとpageの混同
解決手順
ステップ1:ページネーションの問題を診断する
# ページネーション設定を確認
wp eval "
global \$wp_query;
echo 'posts_per_page: ' . get_option('posts_per_page') . PHP_EOL;
echo 'found_posts: ' . \$wp_query->found_posts . PHP_EOL;
echo 'max_num_pages: ' . \$wp_query->max_num_pages . PHP_EOL;
echo 'current paged: ' . get_query_var('paged') . PHP_EOL;
echo 'current page: ' . get_query_var('page') . PHP_EOL;
echo 'is_front_page: ' . (is_front_page() ? 'true' : 'false') . PHP_EOL;
echo 'permalink_structure: ' . get_option('permalink_structure') . PHP_EOL;
"
# rewriteルールにpagedが含まれているか確認
wp eval "
\$rules = get_option('rewrite_rules');
\$paged_rules = array_filter(array_keys(\$rules), fn(\$k) => str_contains(\$k, 'paged'));
echo 'Paged rewrite rules: ' . count(\$paged_rules) . PHP_EOL;
foreach (array_slice(\$paged_rules, 0, 3) as \$rule) {
echo ' ' . \$rule . PHP_EOL;
}
"
ステップ2:パーマリンクとrewriteルールを修正する
# パーマリンクをリセット(最初に試すこと)
wp rewrite flush --hard
# フロントページが固定ページの場合の設定確認
wp eval "
echo 'show_on_front: ' . get_option('show_on_front') . PHP_EOL;
echo 'page_on_front: ' . get_option('page_on_front') . PHP_EOL;
echo 'page_for_posts: ' . get_option('page_for_posts') . PHP_EOL;
"
// テンプレートファイル: メインクエリのページネーション(正しい使い方)
// ✅ 正しい: the_posts_pagination() を使用
the_posts_pagination([
'mid_size' => 2,
'prev_text' => '« 前のページ',
'next_text' => '次のページ »',
]);
// ✅ 正しい: previous_posts_link / next_posts_link
previous_posts_link('« 前のページ');
next_posts_link('次のページ »', $wp_query->max_num_pages);
// ❌ 間違い: query_posts() はメインクエリを壊す
// query_posts('posts_per_page=5'); // 使用禁止
// ✅ 正しい: pre_get_posts フックでメインクエリを変更
add_action('pre_get_posts', function(WP_Query $query): void {
if (!is_admin() && $query->is_main_query() && $query->is_home()) {
$query->set('posts_per_page', 5);
}
});
ステップ3:カスタムWP_Queryのページネーションを修正する
// テンプレートファイル: カスタムWP_Queryでのページネーション
// ✅ 正しい: pagedパラメーターを正しく渡す
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
// フロントページの場合はpageを使用
if (is_front_page()) {
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
}
$custom_query = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 5,
'paged' => $paged, // 必須:現在のページ番号
'post_status' => 'publish',
]);
if ($custom_query->have_posts()) :
while ($custom_query->have_posts()) :
$custom_query->the_post();
// 投稿を表示
endwhile;
// ページネーションを表示($custom_queryのmax_num_pagesを渡す)
the_posts_pagination([
'total' => $custom_query->max_num_pages, // 必須
'mid_size' => 2,
'prev_text' => '«',
'next_text' => '»',
]);
endif;
wp_reset_postdata();
// functions.php: paginate_links() でカスタムページネーションを実装
function custom_pagination(int $max_num_pages, int $current_page): string {
if ($max_num_pages <= 1) {
return '';
}
$links = paginate_links([
'base' => str_replace(PHP_INT_MAX, '%#%', esc_url(get_pagenum_link(PHP_INT_MAX))),
'format' => '?paged=%#%',
'current' => max(1, $current_page),
'total' => $max_num_pages,
'type' => 'array',
'prev_text' => '«',
'next_text' => '»',
]);
if (!$links) {
return '';
}
return '<nav class="pagination"><ul>'
. implode('', array_map(fn($link) => "<li>{$link}</li>", $links))
. '</ul></nav>';
}
ステップ4:固定フロントページのページネーションを修正する
// functions.php: 固定フロントページでのページネーション対応
// 通常は paged ではなく page クエリ変数を使う
// フロントページに投稿一覧をページネーション付きで表示する場合
add_action('pre_get_posts', function(WP_Query $query): void {
if ($query->is_main_query() && is_front_page() && !is_admin()) {
$query->set('posts_per_page', 10);
// フロントページでは paged ではなく page を使う
$paged = get_query_var('page') ?: 1;
$query->set('paged', $paged);
}
});
# .htaccess: ページネーションのURLルールが壊れている場合
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 重要: WordPress標準のルール(ページネーションが含まれる)
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
ステップ5:AJAXページネーションを実装する
// functions.php: AJAXで非同期ページネーション
add_action('wp_enqueue_scripts', function(): void {
wp_enqueue_script(
'ajax-pagination',
get_template_directory_uri() . '/js/ajax-pagination.js',
['jquery'],
'1.0',
true
);
wp_localize_script('ajax-pagination', 'ajaxPagination', [
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('ajax_pagination'),
]);
});
add_action('wp_ajax_load_more_posts', 'handle_load_more_posts');
add_action('wp_ajax_nopriv_load_more_posts', 'handle_load_more_posts');
function handle_load_more_posts(): void {
check_ajax_referer('ajax_pagination', 'nonce');
$page = (int) ($_POST['page'] ?? 1);
$query = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 5,
'paged' => $page,
'post_status' => 'publish',
]);
ob_start();
while ($query->have_posts()) {
$query->the_post();
get_template_part('template-parts/content');
}
$html = ob_get_clean();
wp_reset_postdata();
wp_send_json_success([
'html' => $html,
'max_num_pages' => $query->max_num_pages,
]);
}
注意事項
query_posts()は絶対に使用しないでください。メインクエリを上書きしてページネーションを破壊します。代わりにpre_get_postsフックまたはWP_Queryを使用してください- カスタム
WP_Queryでthe_posts_pagination()を使う場合は必ず'total' => $custom_query->max_num_pagesを渡してください。これを省略するとメインクエリのページ数が使用されます - 固定ページをフロントページに設定している場合、ページネーションには
pagedではなくpageクエリ変数が使用されます。get_query_var('page')を使うか、両方を確認してください
まとめ
WordPressページネーション不動作の解決は①$wp_query->max_num_pages・found_posts・get_query_var('paged')を確認・permalink_structureの設定確認・pagedのrewriteルール確認、②wp rewrite flush --hardでルールをリセット・query_posts()をpre_get_postsフックに置き換え・the_posts_pagination()を正しく使用、③カスタムWP_Queryにpagedパラメーターを渡す・the_posts_pagination(['total' => $query->max_num_pages])でページ数を明示・wp_reset_postdata()でクエリをリセット、④固定フロントページはget_query_var('page')を使用・pre_get_postsでフロントページのページ数を設定、⑤AJAXページネーションでwp_ajax_フックを実装・wp_create_nonceでセキュリティトークンを付与・wp_send_json_successでHTML片を返却の手順で解決します。