固定ページにサムネイル付き記事一覧

サムネイル抜粋付き一覧

サムネイル抜粋付き一覧

wordpress 2.8.4 の固定ページ(page.php)に、特定のカテゴリのすべての記事一覧を、サムネイルと抜粋付きで表示したくなりました。
こんな感じ。フォトブログ一覧

そこで基本的な The loop で、マルチループ(二重・複合ループ)するのにドツボにはまったので、メモしておきます。

The loop のマルチループのツボ

page.php をコピーして、list_page.phpを作るとします。

[sourcecode language=”php” firstline=””]
<?php
/*
Template Name: list_page
*/
get_header(); ?>

<?php if (have_posts()) : the_post(); ?>
/* ★1 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

/* ★2 特定カテゴリの一覧用ループ start */
<?php
$my_query = new WP_Query(‘cat=20&showposts=-1’);
if ($my_query->have_posts()) :
while ($my_query->have_posts()) : $my_query->the_post(); ?>
/* 記事のタイトル表示 */
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php
endwhile;
endif;
?>
/* ★2 特定カテゴリの一覧用ループ end */

/* ★3 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

<?php endif; ?>
<?php get_footer(); ?>
[/sourcecode]

07行目の if (have_posts()) : the_post(); が、固定ページの基本のループ(実際は記事が1つしか存在していないのでwhileでループさせてはいませんが)。
これでループ内の関数、the_title()などに、この固定ページのタイトルなどがセットされます。暗黙のウチに、$wp_query オブジェクトにリクエストの情報がセットされています。

13行目の、$my_query = new WP_Query(‘cat=20&showposts=-1’); で、記事一覧を出すための、ループをセットします。カテゴリIDを20として、showpostsの-1は全ての記事という意味で、新しいループのクエリを$my_query オブジェクトにセット。

これで、$wp_query のループと、$my_query のループの二重ループになり、それぞれ異なる値を参照できるはずです。
ところが、実行してみると、★1のタイトルと★3のタイトルは、同じ固定ページ($wp_query)のタイトルにならなくてはならないのですが、★1はOKでも、★3は、$my_query ループの最後の記事のタイトルになってしまっています。
なんでやー!!

そこで、「★2 特定カテゴリの一覧用ループ start」の前に、下記の行をたして、$wp_queryをバックアップし、

[sourcecode language=”php” firstline=””]
<?php $temp_query = clone $wp_query; ?>
[/sourcecode]

「★2 特定カテゴリの一覧用ループ end」のあとに、

[sourcecode language=”php” firstline=””]
<?php $wp_query = clone $temp_query; ?>
[/sourcecode]

を付け足して、バックアップしたモノを戻すようにしました。
が、これでも、★3は $my_query の最後のタイトルになってる~!

★3の前に、 $wp_query->post->post_title を表示させてみると、なんと、バックアップしてもしなくても、ちゃんと $wp_query は元の固定ページのタイトルを保持していることが判りました。

で、物は試しに、「★2 特定カテゴリの一覧用ループ end」のあとで、$post をセットし直してみてはどうかと思いつく。

[sourcecode language=”php” firstline=””]
<?php $post = $wp_query->post; ?>
[/sourcecode]

を追加してみたら、OK!!

追記(2009/10/24)
上のやり方では動作しないケースが発生。
以下の方が、良いのかも。

[sourcecode language=”php” firstline=””]
<?php have_posts(); the_post(); ?>
[/sourcecode]

結果オーライの二重ループ。

[sourcecode language=”php” firstline=””]
<?php
/*
Template Name: list_page
*/
get_header(); ?>

<?php if (have_posts()) : the_post(); ?>
/* ★1 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

/* ★2 特定カテゴリの一覧用ループ start */
<?php
$my_query = new WP_Query(‘cat=20&showposts=-1’);
if ($my_query->have_posts()) :
while ($my_query->have_posts()) : $my_query->the_post(); ?>
/* 記事のタイトル表示 */
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php
endwhile;
endif;
?>
/* ★2 特定カテゴリの一覧用ループ end */

/* 謎の呪文 */
<?php $post = $wp_query->post; ?>
<?php //あるいは have_posts(); the_post(); ?>

/* ★3 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

<?php endif; ?>
<?php get_footer(); ?>
[/sourcecode]

各記事の一つ目の画像をサムネイル表示

つぎは、各記事ごとに、一つ目の画像をサムネイル表示したいところ。
これは最強すぎるプラグインが公開されていました。

QF-GetThumb 1.1.3 リリース
このプラグインは、投稿記事や指定されたコード内にあるイメージタグを解析し、そのうち1点のみを参照元イメージ画像サムネイル化及びキャッシュ化するという機能を持っています。記事一覧等のインデックス生成や、携帯コンテンツ向のテーマカスタマイズを目的に開発しました。

[sourcecode language=”php” firstline=””]
<?php if ($my_count++ < 15) : ?>
<p class="alignleft"><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php echo the_qf_get_thumb_one(‘num=0&width=100’); ?></a></p>
<?php endif; ?>
[/sourcecode]

こんな感じにコードするだけで、呼び出した時点で自動的にサムネイル画像が作成され、当該箇所がサムネイルに対するimgタグに置き換えられます。おそろべし便利さ。
さすがに、全記事のサムネイルを出すと重くなりそうなので、最新から15件分だけ出すようにしたりして。

ローカル環境で、QF-GetThumb がエラー

ちなみに[post=”1532″ text=”前回作ったローカル環境”]では、imagecreatefromjpeg()関数が無いとかいうエラーが出て作動しませんでした。
どこで定義されている関数かとググったら、php の GD ライブラリにあるとのこと。
php.ini の
;extension=php_gd2.dll
をコメントアウトして、Apacheを再起動すればOKでした。

the_excerpt()をナントカする

投稿の抜粋を、文末に […](角括弧+三点リーダー)をつけて表示する、the_excerpt() が、勝手に‹p›タグを付加したり、「続きを読む」リンクになっていない[…]も格好悪い気がして、これをナントカすることに。

/wp-includes/default-filters.php内にある、add_filter(‘the_excerpt’, ‘wpautop’); が諸悪の根源らしいので、remove_filterでこいつを抑制すれば良いみたい。
テーマの、function.phpの最後に、下記を追加。

[sourcecode language=”php” firstline=””]
remove_filter(‘the_excerpt’, ‘wpautop’);
function fdel_tabspc($str){
$str = preg_replace("/(\r|\n|\r\n)/m", "<br>", $str);
$str = preg_replace("/ /", "", $str); //全角スペース削除
$str = preg_replace("/\t/", "", $str); //タブ削除
$str = preg_replace("/\s/", "", $str); //空白削除(何故かこれで改行まで削除されてしまうので冗長に)
$str = preg_replace("/(<br>)+/", "<br />", $str);
$str = preg_replace("/^(<br \/>)/", "", $str);
$str = preg_replace("/(<br \/>)\[\.\.\.\]/", "…", $str);
$str = preg_replace("/\[\.\.\.\]/", "…", $str);
return $str;
}
add_filter(‘the_excerpt’, ‘fdel_tabspc’);
[/sourcecode]

ついでに、改行は活かしつつ、不要なスペースやタブ、空白行を削除し、[…]をただの3点リーダーにしました。
正規表現が下手で、冗長なところは、どなたか直して~。

これを下記のように、$my_queryのループに組み込みました。
[sourcecode language=”php” firstline=””]
<p class="clearfix post_excerpt"><?php the_excerpt(); ?>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">[ 続きを見る ]</a></p>
[/sourcecode]

list_page.phpを汎用にする

テンプレートファイル中に、new WP_Query(‘cat=20&showposts=-1’); とカテゴリーを設定していては、カテゴリーごとにページ用テンプレートファイルを用意しなければなりません。
これは気になるので、カテゴリIDを、固定ページの投稿記事中に設定出来るようにすれば、1つのテンプレートファイルで済むかも。

テンプレートファイルの方のIDを変数にしておく。

[sourcecode language=”php” firstline=”13″]
$my_query = new WP_Query(‘cat=’ . $my_cat . ‘&showposts=-1’);
[/sourcecode]

Exec-PHP を導入してみる

Exec-PHP プラグインを導入すれば、記事中にphpのコードを書けるようになります。
プラグインをインストして有効にし、ユーザー→「あなたのプロフィール」の下部できた「Exec-PHP Settings」というメニューの「Disable WYSIWYG Conversion Warning」にチェックを入れてプロフィールを更新して、新規投稿画面のWarningを非表示にすればOK。

投稿記事中に、

[sourcecode language=”php” firstline=””]
<?php global $my_cat; $my_cat = 3 ?>
[/sourcecode]

と書くようにして、
テンプレートファイルの the_content()の後に、記事一覧のループが来るようにすると、変数が反映されます。

ここまでのまとめ

[sourcecode language=”php” firstline=””]
<?php
/*
Template Name: list_page
*/
get_header(); ?>

<?php if (have_posts()) : the_post(); ?>
/* ★1 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
<div class="textBody">
<?php the_content(); ?>
</div>

/* ★2 特定カテゴリの一覧用ループ start */
<?php
$my_query = new WP_Query(‘cat=’ . $my_cat . ‘&showposts=-1’);
if ($my_query->have_posts()) :
while ($my_query->have_posts()) : $my_query->the_post(); ?>
/* 記事のタイトル表示 */
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php if ($my_count++ < 15) : ?>
<p class="alignleft"><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php echo the_qf_get_thumb_one(‘num=0&width=100’); ?></a></p>
<?php endif; ?>
<p class="clearfix post_excerpt"><?php the_excerpt(); ?>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">[ 続きを見る ]</a></p>
<?php
endwhile;
endif;
?>
/* ★2 特定カテゴリの一覧用ループ end */

<?php $post = $wp_query->post; ?>

/* ★3 この固定ページのタイトル */
<h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

<?php endif; ?>
<?php get_footer(); ?>
[/sourcecode]

追加:カテゴリテンプレートへ適用

さすがに、記事数が多いと重いし、常にサムネイル表示で、ページ送りが出来ると便利だなと、思えてきました。
そこで、category.php をこの形式に変更することにしました。

ここでは二重ループにする必要はないのですが、抜粋表示で情報量が減った分、表示投稿数を増やしたいところです。
そこで、
if (have_posts()) :
の直前に、
query_posts($query_string.’&showposts=10&posts_per_page=10′);
を追加して、クエリを変更します。
posts_per_page が、エントリいくつごとにページを切るかの設定です。表示数の showposts と合わせておきます。

そして、 the_content()があるところを以下のソースに変更するだけでOK。

[sourcecode language=”php” firstline=””]
<p class="clearfix post_excerpt"><?php the_excerpt(); ?>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">[ 続きを見る ]</a></p>
[/sourcecode]

これの方が便利かも。(2009/10/19現在、各カテゴリ表示をこれにしてみました)
特定のカテゴリだけ、一覧表示にしたければ、category-カテゴリID.php とテンプレートファイルを別に作るだけで、中身を書き換えることなくOK。

  • このエントリーをはてなブックマークに追加

コメント

  1. flas_ より:

    はじめまして。wordpressでブログをしている者です!
    二重ループの仕方がわからず悩んでいましたが、この記事を読ませていただいて解決しました。カスタマイズの幅が広がりました。
    ありがとうございます!

  2. nosaku より:

    読んで頂きありがとうございます!
    お役に立ててよかったです!

コメントをどうぞ

メールアドレスが公開されることはありません。