FLAMA WordPress技術ブログ

WordPress関数get_posts()の挙動

WordPressのややこしい挙動シリーズ、第何弾目かわかりませんが、ちょくちょく出てくるので忘れないように書いておこうと思います。

get_posts()というWordPress関数があります。
投稿一覧(またはページ一覧)を取得するものなので、テーマを作る時などには結構使うと思います。

しかしget_posts()には、知らないと混乱する仕様があります。

たとえば、公式リファレンスにならって次のようなコードを書いたとします。

‘date’,
‘order’ => ‘DESC’,
‘include’ => implode(“,”,get_option(‘sticky_posts’)),
‘post_status’ => ‘publish’
);
$posts_array = get_posts( $args ); ?>

これは「先頭に固定」とした投稿のみを抽出することを意図したものです。

では、この条件で「先頭に固定」投稿が1つも無い場合、$posts_arrayの内容はどうなるでしょうか?
結果は「最新の投稿が5件表示される」です。

どうしてこういうことになるのかというと、多少ややこしい条件があるわけです。
ソースコードを見てみましょう。

https://core.trac.wordpress.org/browser/trunk/src/wp-includes/post.php#L1661
これを見るとまず、
includeが指定されている場合posts_per_pageget_option('sticky_posts')の件数となります。
次に、get_option('sticky_posts')の件数は 0 なので、posts_per_pageには 0 がセットされます。
と同時に、post__inには空の配列がセットされるので、検索条件は指定無しになります。
しかしこの際、numberpostsが指定されていないので、numberpostsには初期値の 5 がセットされています。
numberpostsが空または 0 でない場合には、posts_per_pagenumberpostsで上書きされます。

この後、WP_Query::query()にパラメータとして渡されるわけですが、その時点でposts_per_pageが空または 0 の場合には、posts_per_pageget_option( 'posts_per_page' )で上書きされます。
get_option( 'posts_per_page' )は、管理画面での設定値を使うということですので、逆に言えば、管理画面での設定値を使用したいのであれば、あらかじめget_option('sticky_posts')値を取得しチェックの上posts_per_pageとして指定するか、numberpostsを 0 として明示的に指定しなければならない、ということになります。
https://core.trac.wordpress.org/browser/trunk/src/wp-includes/class-wp-query.php#L1759