🏡まったのブログ

いい加減に整理したいカスタム投稿タイプまわりの一覧の出力方法

いったい何回get_posts(), query_posts(), get_terms(), wp_get_object_terms()あたりに振り回されググり直せばいいんだ。いい加減覚えたい。というかWordpressとかPHPとかもう使いたくない。

前提知識

get_posts()new WP_Query()のラッパーであり、だいたいはget_posts()だけでOK。どちらもwp_reset_postdata()が最後に必要。

https://liginc.co.jp/348970

<?php $args = array(
	'posts_per_page'   => 5,
	'offset'           => 0,
	'category'         => '',
	'category_name'    => '',
	'orderby'          => 'date',
	'order'            => 'DESC',
	'include'          => '',
	'exclude'          => '',
	'meta_key'         => '',
	'meta_value'       => '',
	'post_type'        => 'post',
	'post_mime_type'   => '',
	'post_parent'      => '',
	'author'	   => '',
	'post_status'      => 'publish',
	'suppress_filters' => true 
);
$myposts = get_posts( $args ); ?>

<ul> 
<?php foreach ( $myposts as $post ) : setup_postdata( $post ); ?>
	<li>
		<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
	</li>
<?php endforeach; 
wp_reset_postdata();?>

</ul>

今回のユースケース

説明を分かりやすくするために今回のユースケースで使う名前や構造で説明していく。カスタム〇〇とかタクソノミー、タームとか言ってても分けわからんくなるので。標準のpost, page, category, tagは専用の関数とかあるし今回は一切使わない前提でいく。

サイト上で製品とノートという2つの投稿タイプを作る。例えば「Anker PowrCore Ⅲ」という製品と、「モバイルバッテリーの選び方」というノートを投稿し、どちらとも「モバイルバッテリー」という製品カテゴリーに属する記事とする。

カスタム投稿タイプ

  • 製品(product)
    • Anker PowerCore Ⅲ
    • etc..
  • ノート(note)
    • モバイルバッテリーの選び方
    • etc..

カスタムタクソノミーとターム例

  • 製品カテゴリー(product_cat)
    • モバイルバッテリー
      • スマホ用モバイルバッテリー
      • PC用モバイルバッテリー
    • etc..

全製品の一覧

https://gimmicklog.com/wordpress/1408/

全製品カテゴリーの一覧

全製品カテゴリーと言っても、この場合、親と子がごちゃごちゃになった一覧を表示したいというケースは基本ないでしょう。なので親の製品カテゴリーの下に、子の製品カテゴリーをぶら下げてリストにする方法を書きます。

追記予定

最上位の製品カテゴリーだけを出力の一覧

<ul class="category-list">
				<?php 
				$my_tax = 'product_cat';
				$args = array(
					'parent' => 0
				); 
				$parent_terms = get_terms($my_tax, $args);
				if ( !empty( $parent_terms ) ) :
					foreach ( $parent_terms as $pt ) : 
						$pt_id = $pt->term_id;
						$pt_name = $pt->name;
						$pt_url = get_term_link($pt);
						?>
						<li class="pt-list">
							<a href="<?php echo $pt_url; ?>">								
								<span class="title"><?php echo esc_html($pt_name); ?></span>
							</a>							
						</li>
					<?php
					endforeach;
				endif; 
                                ?>
			</ul>

モバイルバッテリーに属する製品の一覧

taxonomy-product_cat.phpというファイル名にするだけで、それをテンプレートとして優先して読み込んでくれ、ループの記述もデフォルトのままで良しなにやってくれる(それがブラックボックス化してしまって怖い点でもあるのだが)。

// taxonomy-product_cat.php
if ( have_posts() ) :

				while ( have_posts() ) : the_post();

					get_template_part( 'preview', get_post_type() );

				endwhile;

			endif;

モバイルバッテリーに属する製品とノートの一覧

「最上位のタームに属するノートだけ出力」といったやり方はキレイなやり方がなくこの方法をとった。

// taxonomy-product_cat.php
                        $terms = wp_get_object_terms( $post->ID, 'product_cat');
			$term_slugs = [];
			foreach ($terms as $term) {
				array_push($term_slugs, $term->slug);
			}

			$note_args = array(
				'post_type' => 'note',
				'post_status' => 'publish',
				'tax_query' => array(
					array(
						'taxonomy' => 'product_cat',
						'field' => 'slug',
						'terms' => $term_slugs,
						'include_children' => true,
					)
				)
			);
			$the_query = new WP_Query( $note_args );

			if ( $the_query->have_posts() ) {
				while ( $the_query->have_posts() ) {
					$the_query->the_post();
					get_template_part( 'preview', get_post_type() );
				}
				wp_reset_postdata();
			} else {
				// no posts found
			}

// ここからは製品
if ( have_posts() ) :

				while ( have_posts() ) : the_post();

					get_template_part( 'preview', get_post_type() );

				endwhile;

			endif;

モバイルバッテリーだけでなくスマホ用モバイルバッテリー、PC用モバイルバッテリーに属するノートすべてを取ってくる形。get_the_terms()を使ってもいけるかも。

https://haniwaman.com/get-tarm/

スマホ用モバイルバッテリーに属する製品の一覧

スマホ用モバイルバッテリーに属する製品とノートの一覧

追記予定

製品一覧を製品カテゴリーごとに分けて全て出力

  <?php
    $post_type = 'product';
    $taxonomy_name = 'product_cat';
    $args = array(
        'order' => 'ASC',
    );
    $taxonomys = get_terms($taxonomy_name, $args);

    if (!is_wp_error($taxonomys) && count($taxonomys)) {
        foreach ($taxonomys as $taxonomy) :
            $tax_posts = get_posts(array(
                'post_type' => $post_type,
                'posts_per_page' => 10,
                'order' => 'ASC',
                'tax_query' => array(
                    array(
                        'taxonomy' => $taxonomy_name,
                        'field' => 'slug',
                        'terms' => array($taxonomy->slug),
                        'include_children' => true,
                    )
                )
            ));

            if ($tax_posts) { ?>
              <h2 id="<?php echo $taxonomy->term_taxonomy_id; ?>"><?php echo esc_html($taxonomy->name); ?></h2>
              <ul>
                  <?php foreach ($tax_posts as $tax_post) : ?>
                      <li>
                          <a href="<?php echo get_permalink($tax_post->ID); ?>">

                              <h3><?php echo get_the_title($tax_post->ID); ?></h3>

                              // アイキャッチ画像を出力したい場合(has_post_thumbnailとthe_post_thumbnailは使えない)
                              <?php if (get_the_post_thumbnail($tax_post->ID)) :  ?>
                                  <?php echo get_the_post_thumbnail($tax_post->ID); ?>
                              <?php else : ?>
                                  <img src="<?php bloginfo('template_url'); ?>/images/no_image.gif" />
                              <?php endif; ?>

                              // カスタムフィールド値を出力したい場合
                              <?php if (get_field('sub_title', $tax_post->ID)) { ?>
                                  <h4><?php the_field('sub_title', $tax_post->ID); ?></h4>
                              <?php } ?>

                          </a>
                      </li>
                  <?php endforeach;
                    wp_reset_postdata(); ?>
              </ul>
      <?php }
        endforeach; ?>
  <?php } else { ?>
      <p>投稿はありません。</p>
  <?php } ?>

// 引用元: https://gimmicklog.com/wordpress/1408/