WP_Queryのposts_per_pageが効かないので解決を図った
最近、ちょくちょくワンオフテーマを作っているんだけど、従来ならget_posts()だとかquery_posts()とかで取っていた投稿データをWP_Queryで取得することが多くなった。
で、今やってる仕事でもWP_Queryを使って投稿を取得しようとしたんだが、従来と同じ感覚でどうやっても、posts_per_pageが効かないという現象に遭遇した。
まぁ同じことで調べている人いっぱいいるだろうな~と思ったんだけど、いざ検索エンジン頼りに調べてもみても、出るのは殆どがget_posts()とかquery_posts()の情報。
埒が明かないので、とりあえず小一時間頭を捻って試行錯誤して、ようやくこの問題の解決を図った。
で、その解決方法だが、「投稿を全取得する場合」と「投稿を指定の数(1個とか4個とか10個とか)で固定で取得する場合」とで方法が変わる。
まずは、「投稿を全取得する場合」。これはCodexにも書かれており、
$query = new WP_Query( array( 'post_type' => 'post', 'nopaging' => true // ←こいつ ) ); if ( $query->have_posts() ): while ( $query->have_posts() ) : $query->the_post(); ~~~~~ endwhile; wp_reset_postdata(); endif;
nopagingのプロパティをtrueにすると解決可能。posts_per_pageの指定は要らない。
次は、「投稿を指定の数で固定で取得する場合」。
これは引数だけでは何ともならないので取得したクエリ変数のオブジェクトの内容そのものを書き換える必要がある。
$query = new WP_Query( array( 'post_type' => 'post',// ↓180927 追記・修正。これがないと$query->post_countで指定した値が管理画面の投稿表示数より大きいときにエラーする// ↓190611 修正。 // これより下記のコードでの$query->post_countをきちんとセットすればこのposts_per_pageはあってもなくてもどっちでもいいみたい // ただし、$query->post_countに設定する値が管理画面で設定するページングの値を上回っている場合は指定を推奨 'posts_per_page' => 4, ) ); $query->post_count = 4; // ←こいつ // 190611 追記。 // $query->post_countがページング内での実表示投稿数を上回った際に空のループができるので、 // 当該のオブジェクト変数へ実表示投稿数を再セットする if ( $query->post_count > count( $query->posts ) ) : $query->post_count = count( $query->posts ); endif; if ( $query->have_posts() ): while ( $query->have_posts() ) : $query->the_post(); ~~~~~ endwhile; wp_reset_postdata(); endif;
上記のようにWP_Queryを変数に突っ込んだ後で、そのクエリ変数のpost_count(上記のコードの$query->post_count)を変更する。
とりあえず、これで指定の数での投稿データの取得が可能。
どこかに情報があれば、小一時間も考えたり悩んだりする必要がなかったものの(´・ω・`)
…つーか、小一時間も悩んだのは「投稿を指定の数で固定で取得する場合」。お前のせいだよ。
WP_Queryのページ関係の引数を全て入れたのにも関わらず動かず・・・。
いやさ、「投稿を全取得する場合」でposts_per_pageを入れずにnopaging入れて取得できた時点でposts_per_pageに既に疑いの匂いがプンプンしたんだよ…。
で、こりゃおかしいぞと思って、var_dump()で出してきてみりゃ、なぜかクエリ変数の投稿データのposts_per_pageは管理画面の投稿表示数になっていた。
…ちなみに、このposts_per_pageはオブジェクト内に複数あるが、そのうち実際のループに使われるもののほうがピンポイントで管理画面の投稿表示数になっていた始末である。
ともあれ、こうしてクエリ変数(上記で言う$query)の中身を調べたのが功を奏し、それっぽい値(件のpost_count)を見つけて、直接書き換えてみたらものの見事にBINGOしたわけである。
…まぁ本来、表示する投稿数であるpost_countを直接弄るのも、この際致し方ない。
解決方法を見つけてしまえば、気持ち的にもコード的にもいろいろ氷解。
したんだよ?…したんだが。
上記のコードの中にposts_per_pageの文字列は何一つとして入っちゃいない。
WP_Queryのposts_per_pageさん、完全にただの要らない子やん…。
【180927修正】いや、WP_Queryのposts_per_pageはやっぱり普通に必要やったわ。
posts_per_pageを指定しないと、$query->post_count = 4;を管理画面の表示投稿数より多く指定したときにループでエラーするので(´・ω・`)
ってわけで、posts_per_pageと$query->post_countは同時に指定しましょう。
【190611修正】一応、もう少し掘り下げて調べてみた上で追記。
実際のところ、$query->post_countのセットと、それの空ループ対策ができていれば、posts_per_pageはあまり必要がなくなる。
というか、管理画面で設定するページングの数よりも$query->post_countが上回っていないのであれば、別にあってもなくてもどっちでもいい。
以前、コメントしてくださった人の言葉の意味はこれだったか。感謝。
何にしても、WP_Queryのposts_per_pageが効かない環境であれば、解決方法の一つとしてこういった形になってくると思う。
まぁ、どうにしても解せない。
とりあえず、この後も作業があるので今回はここまで。