「&」はHTMLエンティティ( & と ; で囲まれた文字列)の1つで、HTMLでは「&」(アンパサンド)を示すものになりますね。( 「&」も「&」に同じ)

ワードプレスの自作プラグインとかでWP_Queryを使って記事の一覧表示させてページネーションを付けた場合、ページネーションの数字(2ページ目とか)をクリックすると、この「&」の「&」を除いた「#038;」という文字列がURLに入ってしまう場合があります。

原因を色々調べた結果、URLにページネーションとは関係のないキーが入る場合(今回ご紹介するケースでは「&settings-updated=true」)、ページネーションを表示する関数の中で「&」を「&」にエスケープして、結果ページネーションリンク(URL)に「#038;」が入ってしまうようです。

その具体的症状や原因、解決する方法を参考までに。

実際のコードと症状

自作プラグインを作っていたらURLになぜか「#038;」が入り、
ページネーションがうまくできない。
(ページ番号をクリックしてもそのページが表示されない)

その時のコードは以下のような感じです。

ページネーションのコードは、ワードプレスの公式リファレンス(基本的な例の箇所)を基本にして若干変えているだけ。

(ワードプレスの管理画面だと get_query_var()がうまく動作しないので$_GET[‘paged’]でページ番号($paged)を取得しているところが異なる。詳しくは 管理画面や設定ページではget_query_varが使えない?!を参照 ))

これで実際に一覧表示させてみるとうまく動作しているようですが、
例えば以下のような操作をするとURLに「#038;settings-updated=true」が入り、ページネーションがうまく動作しなくなってしまいます。
(ページ番号をクリックしてもそのページが表示されない)

  • 1)ワードプレス管理画面の「設定」メニューからプラグインの設定画面を表示
    (この時のURLは以下)
    http://xxxx/options-general.php?page=jin-more-tag-auto
  • 2)同じページにあるSettings APIを使った設定を保存
    (保存後のURLは以下)
    http://xxxx/options-general.php?page=jin-more-tag-auto
  • 3)その後、記事一覧のページネーションで「2ページ目」をクリックすると以下のURLになる
    http://xxxx/options-general.php?page=jin-more-tag-auto#038;settings-updated=true&paged=2

※)補足
「More Tag Auto」というプラグインを作り、その設定画面のURLを「jin-more-tag-auto」としているので、URLは http://xxxxx/options-general.php?page=jin-more-tag-auto となっている

原因と解決法

なぜ「#038;~」 といった文字列がURLに入るのか、
その原因はページネーションのコード中にあるesc_url()関数とget_pagenum_link()関数にあるようです。(35行目)

詳しくは Paginate Link generate additional #038(英語)で分かりましたが、
そもそもget_pagenum_link() 関数は、初期状態(第二引数で false を指定しない場合)では esc_url()を使ってURLを返すようになってます。(つまり esc_url(get_pagenum_link($big) ) は2重でエスケープしている)

esc_url() は「&」をHTMLエンティティの「&」に変換し、
(上の例では「&settings-updated=true」となり)
ページネーションを表示する paginate_links()(39行目)がこの「&」以降「#038;settings-updated」をキー(「true」を値)と解釈してしまい、結果URLにそれが表示される、となるようです。

※)今回の例では、記事一覧を表示する同じ画面上に別の設定があり、その設定を保存したことでページネーションのリンクURLに余計な「&settings-updated=true」が付き、その「&」がget_pagenum_link() の中で変にエスケープされて「&」になった、となりそうです)

また、get_pagenum_link() の値を元にページネーションを表示する paginate_links()(39行目)は、関数リファレンスにあるソースコードを見ると、内部的に一旦デコード(html_entity_decode)してesc_url()を使ってURLを返すようになってます。

以上からURLに出てくる「#038;」の表示をなくすには以下の3つの対応が考えられる、ってことになりますね。

  • その1)そもそも get_pagenum_link() では esc_url() を使用しない
  • その2)get_pagenum_link()の返り値をHTMLエンティティデコードしておく
    (「#038」を「&」に戻しておく)
  • その3)get_pagenum_link()の返り値に含まれる「&」を「&」に置き換える

この3つの方法を各々試してみると、
いずれも「#038;」がなくなり、正しいURLでページネーションも動作するようです。

私の場合、一番お手軽な「その1」を採用しました。

以上、ご参考までに。

早期退職して海外で奮闘する JIN のメールマガジン

時間や場所に縛られず稼いだJINが教える

~ 最短で月収10万円稼げるようになる方法 ~

お名前(全角文字)

隣のあの人にも、思わず教えたくなる秘密

配信停止は、いつでもできます

迷惑メールは一切配信されませんので、ご安心くださいね

自らの手で未来を変える力を手に入れる!