WordPress

WordPress のややこしいループ処理はこう書けばいい

TABLEofCONTENTS

慣れてないとわかりにくい、慣れてくるとめんどくさい。そんな WordPress のループ処理をシンプルにする方法。

メインループの場合

これを、

while ( have_posts() ) :
  the_post();
  // 記事を表示
endwhile;

こう。

do_action( 'mytheme/loop', '記事出力テンプレート名' );

もちろん、これだけだとシー…ンとしてしまうので functions.php に以下のような処理を書いておきます。

/**
 * WordPress main loop.
 *
 * @param string $slug The slug name for the generic template.
 * @param string $name The name of the specialised template.
 */
add_action( 'mytheme/loop', function ( $slug, $name = '' ) {
  while( have_posts() ) :
    the_post();
    get_template_part( $slug, $name );
  endwhile;
} , 10, 2 );

無名関数を使ってますので PHP 5.3以上の書き方です。5.2 以下の場合はいつものように add_action() の第2引数は関数名にしましょう。$slug, $nameget_template_part() と同じ引数です。記事サマリー部分を別テンプレートにするのも single.php なんかに詰め込みすぎないという点でおすすめです。

逆にメンドそうですか?では…

サブループの場合

これや、

$query = new WP_Query( $args );
while ( $query->have_posts() ) :
  $query->the_post();
  // 記事を表示
endwhile;
wp_reset_postdata();

これを、

$my_posts = get_posts( $args );
foreach ( $my_posts as $post ) :
  setup_postdata( $post );
  // 記事を表示
endforeach;
wp_reset_postdata();

こう。

do_action( 'mytheme/subloop', $args, '記事出力テンプレート名' );

ちょっとイケてる気がしてきましたか?もちろん、これもこれだけだとシーーー……ンなので functions.php に下のような処理を書いておきます。

/**
 * Loop post objects.
 *
 * @param array|string query parameters or query string.
 * @param string $slug The slug name for the generic template.
 * @param string $name The name of the specialised template.
 */
add_action( 'mytheme/subloop', function ( $args, $slug, $name = '' ) {
  $query = new WP_Query( $args );

  while ( $query->have_posts() ) :
    $query->the_post();
    get_template_part( $slug, $name );
  endwhile;
  
 // do_action( 'mytheme/pagination', $query );

  wp_reset_postdata();
}, 10, 3 );

または…

add_action( 'mytheme/subloop', function ( $args, $slug, $name = '' ) {
  global $post;
    
  $posts = get_posts( $args );
  
  foreach ( $posts as $post ) :
    setup_postdata( $post ) ;
    get_template_part( $slug, $name );
  endforeach;
  
  wp_reset_postdata();
}, 10, 3 );

これを一回コピペしておけば、実際にループしたい場所に do_action() を書けば済みます。ちなみに wp_reset_query()query_posts() の後処理用なので必要ありません。

まとめ

オレオレ親テーマ・フレームワークなどにこういった action の処理を忍ばせておくと、テンプレートファイルはスッキリ見通しが良くなりますね。何だったらよくあるこういうのも、

if ( function_exists( 'wp_pagenavi' ) ) wp_pagenavi();

こうすれば、

do_action( 'pagination' );

いいと思いますよ。

以上、アクションベーステーマコーディング部からの提言でした。