WordPressは、いわゆるブログのようにトップページに記事の一覧が並ぶという構成だけでなく、トップページは静的ページ、ブログは別のURL以下で展開、というような、一般的な企業サイトのような構成にすることも可能です。設定は「設定 -> 表示設定 -> フロントページの表示」から行います。
今回後者の構成でサイトを制作していたのですが、ブログ(投稿ページ)に指定したページにて「query_posts()が効かない」問題が発生してしまいました。その際の設定は下記の通り。
設定 -> 表示設定 -> フロントページの表示
固定ページを選択
- フロントページ 固定ページ「ホーム」(テンプレートsitetop.php)
- 投稿ページ 固定ページ「ブログ」(テンプレートblog.php)
テンプレート
// blog.php query_posts( array_merge( $wp_query->query, array( 'post_type' => array( 'post', 'product' ) ) ) ); load_template( TEMPLATEPATH . '/index.php'); // index.php <?php get_header(); ?> <?php get_template_part( 'loop' ); ?> <?php pagenavi(); ?> <?php get_sidebar(); ?> <?php get_footer(); ?>
問題点
- query_posts()でクエリが上書きされない。
- しかもテンプレート(blog.php)自体が反映されていない(index.phpが適用されている)
調査した結果、2つの点に注意しなければいけないことがわかりました。
1.「投稿ページ」に指定するページにはテンプレートを使わない
問題が発生したときはオフィシャルサイト、ということでWordPress Codexで該当のページを確認。すると…
- 投稿ページ (Posts page) – 投稿を表示するページ名をドロップダウンボックスから選びます。
「選択したページの本文や割り当てたテンプレートは無視され、投稿ページの表示にはテーマの index.php(存在すれば home.php)が使われます。」!どおりでblog.phpが効かないはずだ、「投稿ページ」で指定したページのテンプレートや本文は無視され、タイトルとスラッグだけが利用されるようです。
2.wp_head()より後でquery_posts()をつかうこと
2012.06.13訂正
query_posts()の位置がwp_head()の前後であることは関係なく、「query_posts( array_merge( 通常クエリ, array( 新しいクエリ ) ) );」と通常のクエリに新しいクエリを追記するような記述をしていたことが原因でした。
「1.「投稿ページ」に指定するページにはテンプレートを使わない」に従い、blog.phpをそのままhome.phpに変更。これで大丈夫かと思ったのですが、home.phpは認識するものの、query_posts()は以前有効にならないまま。そこで、さらに下記のように変更。load_template( TEMPLATEPATH . ‘/index.php’);としていた部分を、index.phpに記述していたコードと差し替えてみました。
// home.php query_posts( array_merge( $wp_query->query, array( 'post_type' => array( 'post', 'product' ) ) ) ); <?php get_header(); ?> <?php get_template_part( 'loop' ); ?> <?php pagenavi(); ?> <?php get_sidebar(); ?> <?php get_footer(); ?>
ですが、状況に変化なし…。ループの直前でquery_posts()したほうが良いのかなと思い、query_posts()をget_template_part( ‘loop’ );の直前に移動。
// home.php <?php get_header(); ?> <?php query_posts( array_merge( $wp_query->query, array( 'post_type' => array( 'post', 'movies' ), ) ) ); ?> <?php get_template_part( 'loop' ); ?> <?php wp_reset_query(); ?> <?php pagenavi(); ?> <?php get_sidebar(); ?> <?php get_footer(); ?>
すると、query_posts()がきちんと適用されました。詳しいことは良くわかりませんが、get_header()の中では特にクエリをリセットするような処理をしていないので、もし影響があるとすればwp_head()くらいかなと。ということで、query_posts()は、wp_head()より後、ループの直前で行ったほうが良さそうです。