#2013.03.25追記
この記事を公開してから2年以上が経ちました。このページに記載している実装方法内には、現在おすすめできないものも含まれています。
今後は「今さら…いや今だから「WordPressのトップページに、新着記事○件を表示する」サンプルコードをあげとく」を参照してください。
#2011.12.12追記 記載内容について、加筆訂正しました。
2年ほど面倒を見ていた、元会社の後輩君からWordPressに関する相談が。
どうやら、サイトのトップページにお知らせとブログの新着記事タイトル5件を出したいけど上手くいかないとのこと。
仕上がりはこんな感じ。(右図)
ブログの新着記事+自由記述でお知らせを掲載したいとのこと。
目次
1.現状把握(後輩君がやっていたこと)
- 固定ページ「HOME」を作り、そこへページテンプレート(toppage.php)を適用。
- 「ブログ」は、通常の投稿機能を使用。投稿表示のために、「ブログ」という空の固定ページを作成。
- そして、ダッシュボードの「設定>表示設定>フロントページの表示」で「HOME」を、「投稿ページ」で「ブログ」をそれぞれ選択。
ここまでが設定してありました。
2.症状(何が上手くいっていなかったのか)
肝心の症状を書いてませんでした。
こうなっちゃうんです。
「HOME」っていう固定ページの内容を表示させたいのに、上で取得したブログ新着記事1件目が表示されてしまっている状態です。
3.ソースを見てみよう!
問題の部分だけ抜き出してみます。
<h2>新着ブログ一覧</h2> <dl class="news"> <?php $posts = get_posts('numberposts=5&order=desc'); foreach($posts as $post): ?> <dt><?php echo date("Y年m月d日", strtotime($post->post_date)); ?></dt> <dd><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></dd> <?php endforeach; ?> </dl> <h2>お知らせ</h2> <!-- 投稿ここから --> <?php if(have_posts()): while(have_posts()): the_post(); ?> <div class="post"> <?php the_content(); ?> </div><!-- /.post --> <?php endwhile; endif; ?> <!-- /投稿ここまで -->
ちなみに、「ブログの新着をTOPに表示させる方法はどれを参考にした?」って訊いたら、
「コレ→『[WordPress]ワードプレスでトップページなどに新着情報を表示する方法』だそうですので貼っておきます。
4.解決法その1 順番を変える
私も同様の経験があるのですぐピンときました。
説明抜きで、最も手っ取り早く解決するなら、通常のループを先に持ってくることですかね。
<h2>お知らせ</h2> <!-- 投稿ここから --> <?php if(have_posts()): while(have_posts()): the_post(); ?> <div class="post"> <?php the_content(); ?> </div><!-- /.post --> <?php endwhile; endif; ?> <!-- /投稿ここまで --> <h2>新着ブログ一覧</h2> <dl class="news"> <?php $posts = get_posts('numberposts=5&order=desc'); foreach($posts as $post): ?> <dt><?php the_time('Y年n月j日'); ?></dt> <dd><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></dd> <?php endforeach; ?> </dl>
これだと、ただ順番入れ替えるだけで解決です。
(※日付を出力するタグも、WP標準のthe_timeに変更しています。)
つまりは、上に記述したget_posts() をそのまま引き継いじゃってるんですね。
5.解決法その2 query_posts() 関数を使う ※2013.07.21追記:現在はおすすめしません
いやいや、レイアウト上入れ替えは無理だ、って気持ち分かります。
て、ことで、ちゃんとCodexにも記載があります。
テンプレートタグ/query posts – WordPress Codex 日本語版
query_posts は WordPress ループ で表示される投稿を変更するために使います。
上掲ページの「使い方」のスニペットを参考に、ループ部分を書き換えて
<?php if(have_posts()): while(have_posts()): the_post(); ?>
↓
<?php query_posts(); //コレを追記 if(have_posts()): while(have_posts()): the_post(); ?>
てな感じにしてやればOKです。
あとは念のため、ループ閉じる時にwp_reset_query();を付けるとなおよし。
ついでにCodexページには、新着5件を取得時に使っているget_posts()関数についても説明があります。あわせて参照を!
6.解決法その3 get_posts内で、$postsと$postという変数名を使わない
最後の、この方法が最も良いかと思います。
いつもお世話になってる「まがりんさん」こと@jim0912さんがフォーラムで回答してました。
get_postsを利用されるのであれば、$postsと$postという変数名を使わなければ問題ありません。
WordPress › フォーラム » get_postsでループ処理をした後のthe_contentの内容について
7.解決法その4. setup_postdata($post); を適切に使う 【11/12/12追記】
今まで書いてきた話って、グローバル変数とかそのへんの話をしなくてはいけないので、初心者さんにはちょっとハードルが高いのですよね。
なので今回は割愛するんですが、基本ループの「the_post()」にあたると思われるsetup_postdata($post);
の記述を加えることで、投稿データがグローバル変数に設定されるという…
このへんは、もう少しちゃんと噛み砕いて1本記事書きたいところです。今回は不親切に結果だけ記載。
この方法が、Codexにも書いてある書き方なので変数って何?とか、そういうの分からないひとはこれ使っとけばいいと思います。多分。
<h2>新着ブログ一覧</h2> <dl class="news"> <?php $news = get_posts('numberposts=5&order=desc'); foreach($news as $post): setup_postdata($post); ?> <dt><?php the_time('Y年n月j日(D) H:i'); ?></dt> <dd><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></dd> <?php endforeach; ?> </dl>
以上です。
覚えちゃえば簡単なんですけど、初めてだと焦りますよね。
※引数のnumberposts=5は、query_postsタグに倣ってposts_per_page=5でもOK。