サポート » 使い方全般 » 記事がなかったら祖先タームから取得方法

  • 記事詳細ページ内での
    カスタム投稿のランキングbest5なのですが、

    foreach文で記事が属しているタームから他の記事を取得。
    5に満たない場合、一つ上の階層から取得。



    一番親階層までつづく。

    としたいのですが、どの様に記述すればよろしいでしょうか?
    単純なランキングはかけるのですが、階層またぐと難しすぎてどうしたらいいかわかりません。。。

    よろしくお願いします。

15件の返信を表示中 - 1 - 15件目 (全21件中)
  • 5に満たない場合というのは5件に満たない場合という意味です

    まずは「単純なランキングを取得するコード」をここへ書いて、それに対してアドバイスをもらってはどうでしょう。

    ここまで書いてみたのですが、どうでしょうか??

        <ul class="list-ranking">
    	         
     <?php
    	 
    //現在のタームのidを取得
    $term_id = get_queried_object()->term_id;
     
    //祖先タームのidを取得
    $ancestors = get_ancestors( $term_id, 'my_taxonomy' );
     
    //get_ancestors()は孫から親への順番で配列になるので、順番を入れ替える
    $reversed_ancestors = array_reverse($ancestors); 
     
    
    	         global $post;
    	         $ids = wp_get_object_terms( $post->ID, 'column_category', array( 'fields' => 'ids' ) );
    	         
                 $args = array(
    			  'posts_per_page' => 5,
                  'post_type' => 'column',
                  'meta_key' => 'views',
                  'orderby' => 'meta_value_num',
                  /*'tax_query' => array( array(
    					'taxonomy' => 'column_category',
    					'terms' => $ids,
    					'include_children' => false, // ← 追加		  
    					'operator' => 'AND', // 'IN', 'NOT IN', 'AND' 等
    				) ),
    */
                 );
    
                  $posts = get_posts($args);
    //print_r($posts);
    
    if( !empty( $myposts ) )://もし記事が空でなかったら
                  $i = 0;
                  foreach($posts as $post) :
                  $i++;              
                ?>
    	            <li class="media kanshu">
    	                  <!-- ランキング順位 -->
    	                  <div class="rank"><?php echo $i;?></div>
    	                  <!-- サムネイル -->
    	                  <div class="media-left">
    	                    <a href="<?php the_permalink($posts->ID) ?>"><?php the_post_thumbnail($posts->ID,'thumb'); ?></a>
    	                  </div>
    	                  <!-- 記事 -->
    	                  <div class="media-body">
    	                    <a href="<?php the_permalink($posts->ID) ?>">
    	                      <?php echo $post-> post_title;//mb_substr(strip_tags($post-> post_title),0,40).'...'; ?>
    	                    </a>
    	                  </div>
    	                  
    	                  	
    	                  
    	                <!--監修-->			    
    					<?php 
    							$writers = get_posts(array(
    								'post_type' => 'doctor',
    								'meta_query' => array(
    									array(
    										'key' => 'doctor_supervision', // name of custom field
    										'value' => '"' . get_the_ID() . '"', // matches exaclty "123", not just 123. This prevents a match for "1234"
    										'compare' => 'LIKE'
    									)
    								)
    							));
    	
    							?>
    							
    							<?php if( $writers ): ?>
    							<?php foreach( $writers as $writer ): ?>
    							    <div id="relation">
    								      <div class="media-left">
    									      <a href="<?php echo get_the_permalink($writer->ID); ?>">
    										       <?php echo get_the_post_thumbnail($writer->ID,'doc_thum' ); ?>
    									      </a>
    									  </div>
    									  <div class="article">
    										医師監修 	<span class="clinic">
    													<?php the_field('doctor_clinic', $writer->ID); ?>
    												</span> <a href="<?php echo get_permalink( $writer->ID ); ?>">
    														<?php echo get_the_title( $writer->ID ); ?>
    													</a> <?php the_field('keisho', $writer->ID); ?>
    									  </div>
    							    </div>
    							     
    							<?php endforeach; wp_reset_query();?>
    							<?php endif; ?>
    							<!--//監修-->
    				</li>
    			
    <?php endforeach; wp_reset_query();?>
                  
                  
    <li>準備中です。</li>
    <?php endif; ?>
    <?php wp_reset_query(); ?>
    
    </ul>

    コードが大きくてよくわからないので
    ご最初の質問内容に直接関係すると思われるコードだけに減らしてみました。
    実際に動かしての検証は行なっておらず、コードを減らしただけです。

    これで「単純なランキングを表示するコード」としてちゃんと動作するでしょうか?
    大丈夫なら(ちゃんと動かなければ修正して動く状態にしてから)これをベースに、アドバイスがもらえるのではないかと思います。

    global $post;
    $ids = wp_get_object_terms( $post->ID, 'column_category', array( 'fields' => 'ids' ) );
    
    $args = array(
      'posts_per_page' => 5,
      'post_type' => 'column',
      'meta_key' => 'views',
      'orderby' => 'meta_value_num',
      /*
      'tax_query' => array( array(
        'taxonomy' => 'column_category',
        'terms' => $ids,
        'include_children' => false,
        'operator' => 'AND',
      ) ),
      */
    );
    
    $posts = get_posts($args);
    
    if( !empty( $myposts ) ):	//もし記事が空でなかったら
      foreach($posts as $post) :
    
        // 記事を出力するコードをここに書く
    
      endforeach;
    endif;
    

    すいません、ソースが汚かったです。。。

    まず、条件として5位までランキングを出したいです。

    下記のソースでカスタム投稿の
    記事詳細と同じタームのランキングは表示されます。
    しかし、この場合ですとタームに3つしか記事がなかった場合、
    3位までしかでません、
    なので、その場合は一つ上位のタームからも拾って、
    5位まで表示されるまで階層を登って行きたいです。

    
    <ul class="list-ranking">       
    <?php	 
     global $post;
     $ids = wp_get_object_terms( $post->ID, 'column_category', array( 'fields' => 'ids' ) );
     
     $args = array(
      'posts_per_page' => 5,
      'post_type' => 'column',
      'meta_key' => 'views',
      'orderby' => 'meta_value_num',
        'tax_query' => array( array(
    		'taxonomy' => 'column_category',
    		'terms' => $ids,
    		'include_children' => false, // ← 追加		  
    		'operator' => 'AND', // 'IN', 'NOT IN', 'AND' 等
    	)),
     );
     $posts = get_posts($args);
    ?>
    <li class="media kanshu">
          <!-- ランキング順位 -->
          <div class="rank"><?php echo $i;?></div>
          <!-- サムネイル -->
          <div class="media-left">
            <a href="<?php the_permalink($posts->ID) ?>"><?php the_post_thumbnail($posts->ID,'thumb'); ?></a>
          </div>
          <!-- 記事 -->
          <div class="media-body">
            <a href="<?php the_permalink($posts->ID) ?>">
              <?php echo $post-> post_title;//mb_substr(strip_tags($post-> post_title),0,40).'...'; ?>
            </a>
          </div>
    </li>
    <?php endforeach; wp_reset_query();?>
    </ul>

    実際に動かして検証していませんが、こんな感じでどうでしょう。

    $postid = get_the_ID();  // 現在の投稿のID
    $posttype = get_post_type();  // 現在の投稿の投稿タイプ
    $mytax = 'column_category';  // タクソノミー
    
    // 現在の投稿のターム(の配列)
    $ids = wp_get_post_terms( $postid, $mytax, array( 'fields' => 'ids' ) );
    $to_show = 5;  // あと5つ表示したら終わり
    while ( $to_show > 0 ):
      if ( empty ( $ids ) ) {
        break;  // 投稿にタームがないので表示終わり
      }
    
      // 同じタームを持つ投稿(現在の投稿を除く)を取得
      $args = array(
        'posts_per_page' => $to_show,
        'post_type' => $posttype,
        'meta_key' => 'views',
        'orderby' => 'meta_value_num',
        'tax_query' => array( array(
          'taxonomy' => $mytax,
          'terms' => $ids,
          'include_children' => false,  // タームの現階層のみ
          // 親タームの投稿の方がランキングが高くても子タームの方が優先される
        ) ),
        'post__not_in' => array( $postid );  // 現在の投稿を除く
      );
      $posts = get_posts( $args );
      foreach ( $posts as $post ):
        setup_postdata( $post );
        //
        // ランキングされた投稿を表示
        //
      endforeach;
      wp_reset_postdata();
    
      $to_show -= count( $posts );  // 表示した分を減らす
      // 先祖タームを取得
      // 現在の投稿に2つ以上タームがある場合、最初のタームに絞って先祖を取得
      $ancestors = get_ancestors( reset( $ids ), $mytax, 'taxonomy' );
      if ( count( $ancestors ) < 2 ) {
        break;  // 親タームがないので表示終わり
      }
      $ids = array( $ancestors[1] );  // 親タームを次の対象にする
    endwhile;
    
    • この返信は1 年、 6 ヶ月前に  gblsm さんが編集しました。理由: 誤記訂正

    入れてみたのですが、
    結果は一番親の階層からしか取得してきてないようです。

    https://call-to-beauty.com/column/c423/

    もしかしてforeachの中の書き方が悪いのでしょうか???

      <ul class="list-ranking">
    	  <?php
    
    $postid = get_the_ID();  // 現在の投稿のID
    $posttype = get_post_type();  // 現在の投稿の投稿タイプ
    $mytax = 'column_category';  // タクソノミー
    
    // 現在の投稿のターム(の配列)
    $ids = wp_get_post_terms( $postid, $mytax, array( 'fields' => 'ids' ) );
    $to_show = 5;  // あと5つ表示したら終わり
    while ( $to_show > 0 ):
      if ( empty ( $ids ) ) {
        break;  // 投稿にタームがないので表示終わり
      }
    
      // 同じタームを持つ投稿(現在の投稿を除く)を取得
      $args = array(
        'posts_per_page' => $to_show,
        'post_type' => $posttype,
        'meta_key' => 'views',
        'orderby' => 'meta_value_num',
        'tax_query' => array( array(
          'taxonomy' => $mytax,
          'terms' => $ids,
          'include_children' => false,  // タームの現階層のみ
          // 親タームの投稿の方がランキングが高くても子タームの方が優先される
        )),
        'post__not_in' => array( $postid )  // 現在の投稿を除く
      );
      $posts = get_posts( $args );
      foreach ( $posts as $post ):
        setup_postdata( $post );
        //
        // ランキングされた投稿を表示
        //
        
        
        ?>
    
    	            <li class="media kanshu">
    	                  <!-- ランキング順位 -->
    	                  <div class="rank"><?php echo $i;?></div>
    	                  <!-- サムネイル -->
    	                  <div class="media-left">
    	                    <a href="<?php the_permalink($posts->ID) ?>"><?php the_post_thumbnail($posts->ID,'thumb'); ?></a>
    	                  </div>
    	                  <!-- 記事 -->
    	                  <div class="media-body">
    	                    <a href="<?php the_permalink($posts->ID) ?>">
    	                      <?php echo $post-> post_title;//mb_substr(strip_tags($post-> post_title),0,40).'...'; ?>
    	                    </a>
    	                  </div>
    	                  
    	                  	
    				</li>
    			
    <?php
      endforeach;
      wp_reset_postdata();
    
      $to_show -= count( $posts );  // 表示した分を減らす
      // 先祖タームを取得
      // 現在の投稿に2つ以上タームがある場合、最初のタームに絞って先祖を取得
      $ancestors = get_ancestors( reset( $ids ), $mytax, 'taxonomy' );
      if ( count( $ancestors ) < 2 ) {
        break;  // 親タームがないので表示終わり
      }
      $ids = array( $ancestors[1] );  // 親タームを次の対象にする
    endwhile;       
    ?>
    <?php wp_reset_query(); ?>
    
    </ul>

    もしかしてforeachの中の書き方が悪いのでしょうか???

    そのようですね。1行ずつ、それぞれの行がどのような働きをするコードなのか確認していけば、間違いが見つかると思います。

    それから、私が提示したコードにも一ヶ所、誤りがありました。ごめんなさい。
    下記の部分を差し替えてください。
    間違ったコード:

    $ids = wp_get_post_terms( $postid, $mytax, array( 'fields' => 'ids' ) );
    

    正しいコード:

    $ids = array();
    $terms = get_the_terms( $postid, $mytax );  // タームのオブジェクトの配列
    if ( ! is_wp_error( $terms ) && $terms ) {  // 投稿にタームがついている時だけ
      foreach ( $terms as $term ) {
        $ids[] = $term->term_id;  // タームIDの配列を作る
      }
    }
    
    • この返信は1 年、 6 ヶ月前に  gblsm さんが編集しました。理由: コードを間違えていました
    • この返信は1 年、 6 ヶ月前に  gblsm さんが編集しました。

    ありがとうございます。

    しかし、自分の間違いを見つけることができません、、、
    いきなり前回カテゴリから取得して来てるようです。。。><

    @iguigu さんのコードの中で、下記の部分:

    <li class="media kanshu">
      <!-- ランキング順位 -->
      <div class="rank"><?php echo $i;?></div>
      <!-- サムネイル -->
      <div class="media-left">
      <a href="<?php the_permalink($posts->ID) ?>"><?php the_post_thumbnail($posts->ID,'thumb'); ?></a>
      </div>
      <!-- 記事 -->
      <div class="media-body">
      <a href="<?php the_permalink($posts->ID) ?>">
      <?php echo $post-> post_title;//mb_substr(strip_tags($post-> post_title),0,40).'...'; ?>
      </a>
      </div>
    </li>
    

    を、次のようなコードに置き換えてみてはどうでしょう?

    <li class="media kanshu">
      <!-- ランキング順位 -->
      <div class="rank"><?php echo $i; ?></div>
      <!-- サムネイル -->
      <div class="media-left">
      <a href="<?php the_permalink() ?>"><?php the_post_thumbnail( 'thumb' ); ?></a>
      </div>
      <!-- 記事 -->
      <div class="media-body">
      <a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
      </div>
    </li>
    

    ありがとうございます。

    入れてみたのですが、変わらないですね。。
    表示中の記事はランキングに出てこないようにはなっています。

    https://call-to-beauty.com/column_category/bust/

    右カテゴリの人気ランキングがそうですが、
    取得されるランキングはつねにカテゴリ全体の中のものになってます。。

    現在このようになっています

    
    
       <ul class="list-ranking">
    	  <?php
    
    $postid = get_the_ID();  // 現在の投稿のID
    $posttype = get_post_type();  // 現在の投稿の投稿タイプ
    $mytax = 'column_category';  // タクソノミー
    
    // 現在の投稿のターム(の配列)
    $ids = array();
    $terms = get_the_terms( $postid, $mytax );  // タームのオブジェクトの配列
    if ( ! is_wp_error( $terms ) && $terms ) {  // 投稿にタームがついている時だけ
      foreach ( $terms as $term ) {
        $ids[] = $term->term_id;  // タームIDの配列を作る
      }
    }
    $to_show = 5;  // あと5つ表示したら終わり
    while ( $to_show > 0 ):
      if ( empty ( $ids ) ) {
        break;  // 投稿にタームがないので表示終わり
      }
    
      // 同じタームを持つ投稿(現在の投稿を除く)を取得
      $args = array(
        'posts_per_page' => $to_show,
        'post_type' => $posttype,
        'meta_key' => 'views',
        'orderby' => 'meta_value_num',
        'tax_query' => array( array(
          'taxonomy' => $mytax,
          'terms' => $ids,
          'include_children' => false,  // タームの現階層のみ
          // 親タームの投稿の方がランキングが高くても子タームの方が優先される
        )),
        'post__not_in' => array( $postid )  // 現在の投稿を除く
      );
      $posts = get_posts( $args );
      $i = 0;
      foreach ( $posts as $post ):
      $i++;
        setup_postdata( $post );
        //
        // ランキングされた投稿を表示
        //
        
        
        ?>
    
    <li class="media kanshu">
      <!-- ランキング順位 -->
      <div class="rank"><?php echo $i; ?></div>
      <!-- サムネイル -->
      <div class="media-left">
      <a href="<?php the_permalink() ?>"><?php the_post_thumbnail( 'thumb' ); ?></a>
      </div>
      <!-- 記事 -->
      <div class="media-body">
      <a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
      </div>
    </li>	                  
    	                  
    			
    <?php
      endforeach;
      wp_reset_postdata();
    
      $to_show -= count( $posts );  // 表示した分を減らす
      // 先祖タームを取得
      // 現在の投稿に2つ以上タームがある場合、最初のタームに絞って先祖を取得
      $ancestors = get_ancestors( reset( $ids ), $mytax, 'taxonomy' );
      if ( count( $ancestors ) < 2 ) {
        break;  // 親タームがないので表示終わり
      }
      $ids = array( $ancestors[1] );  // 親タームを次の対象にする
    endwhile;       
    ?>
    <?php wp_reset_query(); ?>
    
    </ul>

    「カテゴリ」と言っておられるのはタクソノミー column_category のタームですよね。

    例を挙げます。そのコードでは
    ある投稿にタームが3つ(a,b,c)付いている場合、ランキングの対象になるのは、aが付いている投稿(aとxが付いていても対象)、bが付いている投稿、cが付いている投稿、の全部です。

    「取得されるランキングはつねにカテゴリ全体の中のものになってます。。」というのは、上の例の場合、aもbもcも付いていない投稿がランキングに出てくるということですか?

    失礼いたしました。
    タームです。

    例で言いますと、
    https://call-to-beauty.com/column_category/bust/

    こちらのタームには記事が5つ以上あるので、
    この中の記事詳細に行った時に表示されるランキングはこのタームの中のPV上位5つになるはず、
    というイメージです。

    こちらのタームには記事が5つ以上あるので、
    この中の記事詳細に行った時に表示されるランキングはこのタームの中のPV上位5つになるはず、

    そのようには、なりません。
    例えば /column/c308/ の記事にはタームが4つ付いていますよね。
    column_biyouseikei_biyouhifuka, bust, body_diet_body_making, kanbotsunyuutou
    この4つのタームのどれか1つでも付いた記事すべてがランキングの対象だからです。

15件の返信を表示中 - 1 - 15件目 (全21件中)
  • トピック「記事がなかったら祖先タームから取得方法」には新たに返信することはできません。