【WordPress】URLに「#038;」が入る問題とその解決方法

WordPressでページネーションを実装する際に、URLに「#038;」が入ってしまうことはありませんか?これは、URLが二重にエスケープ処理されてしまうことが原因で発生します。今回は、この問題の具体的な原因と、その解決方法について紹介します。

URLに「#038;」が入る原因とは?

「&」はHTMLエンティティの一つで、「&」を表す記号です。WordPressで使用するget_pagenum_link()やesc_url()関数は、このエンティティをエスケープすることで、URLに「#038;」が含まれることがあります。

特に、カスタムプラグインやテーマを作成している際、ページネーション機能を実装していると、URLに「#038;」が含まれ、ページ番号をクリックしても正しく動作しないことがあります。

例えば、以下のようなコードでページネーションを実装している場合、URLに「#038;」が混入する可能性があります。

$big = 999999999;
$args_paginate = array(
    'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
    'current' => max(1, $paged),
    'total' => $my_query->max_num_pages,
);
echo paginate_links($args_paginate);

このようなコードを使用していると、get_pagenum_link()とesc_url()によってURLが二重にエスケープされ、&が#038;となってしまうことがあります。

解決方法

この問題を解決するためには、いくつかの方法があります。以下に3つの方法を紹介します。

get_pagenum_link()でesc_url()を使わない

最も簡単な解決策は、get_pagenum_link()関数の第2引数にfalseを渡し、esc_url()を使用しないことです。これにより、二重エスケープが防がれます。

$args_paginate = array(
    'base' => str_replace($big, '%#%', get_pagenum_link($big, false)),
    'current' => max(1, $paged),
    'total' => $my_query->max_num_pages,
);
echo paginate_links($args_paginate);

html_entity_decode()でデコードする

もう一つの方法は、get_pagenum_link()が返す値をhtml_entity_decode()でデコードして、エスケープされた文字を元に戻すことです。

$args_paginate = array(
    'base' => str_replace($big, '%#%', html_entity_decode(get_pagenum_link($big))),
    'current' => max(1, $paged),
    'total' => $my_query->max_num_pages,
);
echo paginate_links($args_paginate);

str_replace()でエンティティを置換する

もう一つのアプローチとして、str_replace()を使って「&」を「&」に置き換える方法もあります。

$args_paginate = array(
    'base' => str_replace(['&', '%#%'], ['&', '%#%'], get_pagenum_link($big)),
    'current' => max(1, $paged),
    'total' => $my_query->max_num_pages,
);
echo paginate_links($args_paginate);

まとめ

WordPressでURLに「#038;」が含まれる問題は、get_pagenum_link()やesc_url()による二重エスケープが原因です。この問題を解決するためには、esc_url()を無効にするか、エンティティをデコードまたは置換する方法があります。最も簡単で効果的な方法は、get_pagenum_link()の第2引数にfalseを渡すことです。