WP-PageNaviとoffsetの関係 -WordPress(ワードプレス)

WordPressを使っていると恐らくお世話になる可能性が高いページネーションプラグインWP-PageNaviの設置で躓いたのでメモメモ。

内容的にはプログラマの方が読んだら「けっ」となる程度であろうこと請け合いですが、デザイナーその他にとってはこの程度のことでも重要な情報なので、世間にシェアする意味で書いてみています。

ページネーションを表示したいのは、ページの中で特定のカテゴリを任意の件数取得して表示するループ処理部分。WP-PageNaviの設置タグを配置したところ、リンクは普通に表示されるのですが、クリックしてページを遷移しても必ず1ページ目が表示されてしまうという現象に悩まされました。

google先生にお伺いしてみたところ、いくつかそれらしき内容がありました。例えばこういう記事

読んでみるとこれらは主にquery_posts()の仕様によって起こる同様の現象について言及されており、有用な情報ではあるのですが、今回は既にこの件はクリアしており、直接の原因ではないっぽい。

困ったなと思いつつしばらくパラメータをいじったりして試行錯誤していると、どうやらquery_postsのoffsetの数値を1以上に指定するとこの現象が起こっているということがわかりました。

ちなみに、その時点での該当部分ソースは以下の通り。

query_posts("showposts=5&offset=4&paged=$page&cat=3");

$pageは、前記リンク等でも解説されていますが、query_posts()が仕様上URLから情報を読み取らないため、ページを取得して渡すための変数です。

さて、offsetが原因とは分かったものの、求められる表示の仕様上それを外すわけには行きません。隣席のプログラマーの方に助けを求めてみたところ、そもそもoffsetというものの性質を考えると、その動きは至極当然なのでは、という答え。

というのも、元々プログラムでページネーションする際、「ページ」という単位でデータを管理しているわけではなく、そのページを作る際に、DBのどこからいくつのデータを引っ張ってくるかを都度計算して指定しているだけなので、offsetを設定するということはその「どこから」という始点を上書きしてしまう処理なのではないか、だから常に4件目から5件の記事が表示されるのではないか、とのこと。

なんてこと。offsetとページ分割はそもそも矛盾してるってことですね。

で、その前提でオススメされたのが、ページごとに計算してoffsetの数値を動的に設定する、という処理。具体的なソースは以下の通り。

$perpage = 5;//ページごとの表示件数
$offset = ($page-1)*$perpage+4;//現在のページに該当するoffset値の計算
query_posts("showposts=$perpage&offset=$offset&paged=$page&cat=3");

これで、無事ページ遷移するようになりました。
なかなか力技ですが、問題なく動いています。

さて、ここでもう一つ問題が発覚です。
WP-PageNaviは、postの総数とページごとの表示件数から最大ページ数を算出して$max_pageという値で保持しているのですが、その値がoffset設定の無い前提の件数で算出されるため、実際の表示件数とずれています。

例えば1ページ5件表示で全12件の場合、offsetを4で指定すると全9件表示で総ページは2ページとなるはずなのですが、それが12件を元に計算して3ページになってしまいます。

そこで今回はさらに、wp-pagenavi.phpに直接手を加えました。バージョンは2.72です。

以下、WP-PageNaviのソースを直接編集しています。

総ページ数は、以下の行で取得されています。

$max_page = $wp_query->max_num_pages;

これを、以下のように変更します。

$max_page = ceil(($numposts-4)/$posts_per_page);

$numpostsと$posts_per_pageは記事数とページごとの表示件数で、WP-PageNaviが取得して持っている値です。それに、今回のoffset値である4で補正をかけて計算したものを$max_pageに代入します。

これで、ページ数も無事算出することができました。

ところがさらに問題がありました。Wp-PageNaviは、他のカテゴリではoffsetせずに使っているので、他のカテゴリで用いられた場合に通常の動作をするよう調整する必要があります。そこで、以下のように分岐処理を加え、特定カテゴリの場合のみoffsetがかかるように設定しました。

$cat = intval(get_query_var('cat'));//query_postsで設定されたカテゴリIDを取得
if($cat==3){//カテゴリIDが3の場合のみ
	$max_page = ceil(($numposts-4)/$posts_per_page);
}else{
	$max_page = $wp_query->max_num_pages;
}

以上でカスタマイズ完了です。

この一連の流れ自体に汎用性はありませんが、WP-PageNaviが動かない際の原因究明や、それでもoffsetをしたいのだというピンポイントな要望に応えるための一助にでもなれば幸いです。