【スポンサーリンク】

Cocoonで作った注目記事ランキングのショートコードを修正した

Cocoonで作った注目記事ランキングのショートコードを修正した

Cocoonテーマのコードを利用して、自前の「注目記事ランキング」を作っていたのですが、更新によってエラーになってしまいました。

改めて、コードを修正して直すことができました。

\記事が役に立ったらシェアしてね/
キーワード
【スポンサーリンク】

1. サイトのPHPにエラーがある

教室ホームページを見たら、ページにエラーが表示されて、レイアウトが崩れていることに気づきました。(2022年10月17日)。

このサイトで重大なエラーが発生しました。

WordPressのトラブルシューティングについては、こちらをご覧ください。

このエラーは、WordPressサイトのPHPコードに、エラーがある場合に表示されます。
処理がエラー箇所で止まってしまうため、それ以降のページ要素やスタイルが全て出力されません。

1-1. Cocoonテーマの更新で自前コードが不整合

エラー箇所を調べてみると、「注目記事ランキング」でした。

Cocoonテーマの更新で自前コードが不整合

このランキングは、Cocoonテーマの「人気記事ショートコード」のソースコードをもとに、私が改造して作っていたものです。

どうも、Cocoonのアップデートで、人気記事ショートコード関数の内部処理が修正され、分岐していた自前のコードが整合性が取れなくなってしまったようです。

ちょうど WordPressが 6.0.2、Cocoonが2.5.0 に更新されたタイミングでした。

Cocoonテーマの更新で自前コードが不整合
Cocoonテーマの更新で自前コードが不整合

Cocoon 2.5は、WordPress 6.0のメジャーアップデートに合わせるため、変更箇所が多かったのだとも思います。

ソースコードからコピーして改造しているので、更新があれば修正が必要になるのは仕方がないです。

2. 更新に合うように自前のコードを作り直す

久々にするコードの修正は集中力が必要なので、後回しにしていました。
ようやく時間が作れたので、コードを修正していきます。

ランキング集計用に別のSQLクエリを渡したいだけなのですが、関数呼び出しの深い部分に書かれているため、直接変更できません。ショートコードの関数の呼び出し元から順に、全て複製して修正しています。

まずは、関係するコードをもう一度洗い出していきます。
GitHubにあるCocoonのソースコードを、前回の修正時の記録をたよりに見ていきます。

関係するコード
  • (lib/shortcodes.php)
  • (lib/html-forms.php)
  • (lib/page-access/access-func.php)

ざっと見て、人気記事ショートコードの関数呼び出しはそのままだったので、該当する部分のコードをテキストエディタにコピーします。

//人気記事ショートコード関数
/** lib/shortcodes.php */

if (!shortcode_exists('popular_list')) {
  add_shortcode('popular_list', 'popular_entries_shortcode');
}
if ( !function_exists( 'popular_entries_shortcode' ) ):
function popular_entries_shortcode($atts) {
  extract(shortcode_atts(array(
    'days' => 'all',
    'count' => 5,
    'type' => 'default',
    'rank' => 0,
    'pv' => 0,
    'cats' => 'all',
    'children' => 0,
    'bold' => 0,
    'arrow' => 0,
    'class' => null,
    'author' => null,
    'post_type' => 'post',
    'horizontal' => 0,
  ), $atts, 'popular_list'));
  $cat_ids = array();
  if ($cats && $cats != 'all') {
    $cat_ids = explode(',', $cats);
  }
  $atts = array(
    'days' => $days,
    'entry_count' => $count,
    'entry_type' => $type,
    'ranking_visible' => $rank,
    'pv_visible' => $pv,
    'cat_ids' => $cat_ids,
    'children' => $children,
    'bold' => $bold,
    'arrow' => $arrow,
    'class' => $class,
    'author' => $author,
    'post_type' => $post_type,
    'horizontal' => $horizontal,
  );
  ob_start();
  generate_popular_entries_tag($atts);
  $res = ob_get_clean();
  return $res;
}
endif;


//人気ランキングリストの取得
/** lib/html-forms.php */
if ( !function_exists( 'generate_popular_entries_tag' ) ):
function generate_popular_entries_tag($atts){
  extract(shortcode_atts(array(
    'days' => 'all',
    'entry_count' => 5,
    'entry_type' => ET_DEFAULT,
    'ranking_visible' => 0,
    'pv_visible' => 0,
    'cat_ids' => array(),
    'children' => 0,
    'exclude_post_ids' => array(),
    'exclude_cat_ids' => array(),
    'bold' => 0,
    'arrow' => 0,
    'class' => null,
    'author' => null,
    'post_type' => 'post',
    'horizontal' => 0,
  ), $atts));

  $records = get_access_ranking_records($days, $entry_count, $entry_type, $cat_ids, $exclude_post_ids, $exclude_cat_ids, $children, $author, $post_type);

  $thumb_size = get_popular_entries_thumbnail_size($entry_type);
  $atts = array(
    'type' => $entry_type,
    'ranking_visible' => $ranking_visible,
    'pv_visible' => $pv_visible,
    'bold' => $bold,
    'arrow' => $arrow,
    'class' => $class,
    'horizontal' => $horizontal,
  );
  $cards_classes = get_additional_widget_entry_cards_classes($atts);
  ?>
  <div class="popular-entry-cards widget-entry-cards no-icon cf<?php echo $cards_classes; ?>">
  <?php if ( $records ) :
    $i = 1;
    foreach ($records as $post):
      $permalink = get_permalink( $post->ID );
      $title = $post->post_title;
      $no_thumbnail_url = ($entry_type == ET_DEFAULT) ? get_no_image_120x68_url($post->ID) : get_no_image_320x180_url($post->ID);
      $w   = ($entry_type == ET_DEFAULT) ? THUMB120WIDTH  : THUMB320WIDTH;
      $h   = ($entry_type == ET_DEFAULT) ? THUMB120HEIGHT : THUMB320HEIGHT;

      $post_thumbnail = get_the_post_thumbnail( $post->ID, $thumb_size, array('alt' => '', 'loading' => 'lazy', 'decoding' => 'async') );
      $pv = $post->sum_count;

      if ($post_thumbnail) {
        $post_thumbnail_img = $post_thumbnail;
      } else {
        $post_thumbnail_img = get_original_image_tag($no_thumbnail_url, $w, $h, 'no-image popular-entry-card-thumb-no-image widget-entry-card-thumb-no-image', '');
      }

      $pv_tag = null;
      if ($pv_visible){
        $pv_text = $pv == '1' ? $pv.' view' : $pv.' views';
        $pv_tag = '<span class="popular-entry-card-pv widget-entry-card-pv">'.$pv_text.'</span>';
      }
      ?>
  <a href="<?php echo $permalink; ?>" class="popular-entry-card-link widget-entry-card-link a-wrap no-<?php echo $i; ?>" title="<?php echo esc_attr($title); ?>">
    <div class="popular-entry-card widget-entry-card e-card cf">
      <figure class="popular-entry-card-thumb widget-entry-card-thumb card-thumb">
        <?php echo $post_thumbnail_img; ?>
        <?php
        $is_visible = apply_filters('is_popular_entry_card_category_label_visible', false);
        $is_visible = apply_filters('is_widget_entry_card_category_label_visible', $is_visible);
        the_nolink_category($post->ID, $is_visible); //カテゴリラベルの取得 ?>
      </figure><!-- /.popular-entry-card-thumb -->

      <div class="popular-entry-card-content widget-entry-card-content card-content">
        <span class="popular-entry-card-title widget-entry-card-title card-title"><?php echo $title;?></span>
        <?php if ($entry_type != ET_LARGE_THUMB_ON): ?>
          <?php echo $pv_tag; ?>
        <?php endif ?>
        <?php generate_widget_entry_card_date('popular', $post->ID); ?>
      </div><!-- /.popular-entry-content -->
      <?php if ($entry_type == ET_LARGE_THUMB_ON): ?>
        <?php echo $pv_tag; ?>
      <?php endif ?>
    </div><!-- /.popular-entry-card -->
  </a><!-- /.popular-entry-card-link -->

  <?php
  $i++;
  endforeach;
  else :
    echo '<p>'.__( '人気記事は見つかりませんでした。', THEME_NAME ).'</p>';//見つからない時のメッセージ
  endif; ?>
  </div>
<?php
}
endif;


/** lib/page-access/access-func.php */

//アクセスランキングを取得
if ( !function_exists( 'get_access_ranking_records' ) ):
function get_access_ranking_records($days = 'all', $limit = 5, $type = ET_DEFAULT, $cat_ids = array(), $exclude_post_ids = array(), $exclude_cat_ids = array(), $children = 0, $author = null, $post_type = 'post'){
  //カテゴリー配列を文字列に変換
  $cat_ids = is_array($cat_ids) ? $cat_ids : array();
  $cats = implode(',', $cat_ids);
  
  //アクセスキャッシュを有効にしている場合
  if (is_access_count_cache_enable()) {
    if ($cat_ids) {
      //子孫カテゴリも含める場合
      if ($children) {
        $categories = $cat_ids;
        $res = $categories;
        foreach ($categories as $category) {
          $res = array_merge($res, get_term_children( $category, 'category' ));
        }
        $cat_ids = $res;
        $cats = implode(',', $res);
      }
    }

    //除外投稿
    $archive_exclude_post_ids = get_archive_exclude_post_ids();
    if ($archive_exclude_post_ids && is_array($archive_exclude_post_ids)) {
      $exclude_post_ids = array_unique(array_merge($exclude_post_ids, $archive_exclude_post_ids));
    }

    $exclude_post_ids = is_array($exclude_post_ids) ? $exclude_post_ids : array();
    $expids = implode(',', $exclude_post_ids);
    $exclude_cat_ids = is_array($exclude_cat_ids) ? $exclude_cat_ids : array();
    $excats = implode(',', $exclude_cat_ids);
    $type = get_accesses_post_type();
    $transient_id = TRANSIENT_POPULAR_PREFIX.'?days='.$days.'&limit='.$limit.'&type='.$type.'&cats='.$cats.'&children='.$children.'&expids='.$expids.'&excats='.$excats.'&author='.$author.'&post_type='.$post_type;
    
    $cache = get_transient( $transient_id );
    if ($cache) {
      if (DEBUG_MODE && is_user_administrator()) {
        // echo('<pre>');
        // echo $transient_id;
        // echo('</pre>');
      } elseif (is_user_administrator()){

      } else {
        return $cache;
      }
    }
  }



  global $wpdb;
  $access_table = ACCESSES_TABLE_NAME;
  // $post_type = 'post';
  $date = get_current_db_date();


  $where = " WHERE {$access_table}.post_type = '$post_type' ".PHP_EOL;
  // _v($where);
  if ($days != 'all') {
    $date_before = get_current_db_date_before($days);
    $where .= " AND {$access_table}.date BETWEEN '$date_before' AND '$date' ".PHP_EOL;
  }

  if (is_ids_exist($exclude_post_ids)) {
    $where .= " AND {$access_table}.post_id NOT IN(".implode(',', $exclude_post_ids).") ".PHP_EOL;
  }
  //3180, 3234
  if (!is_numeric($limit)) {
    $limit = 5;
  }
  //カテゴリを指定する場合
  if (is_ids_exist($cat_ids) || is_ids_exist($exclude_cat_ids)) {
    global $post;
    $term_relationships = $wpdb->term_relationships;
    $term_taxonomy = $wpdb->term_taxonomy;
    $joined_table = 'terms_accesses';
    //カテゴリー指定
    if (is_ids_exist($cat_ids)) {
      $cat_ids = implode(',', $cat_ids);
      //$where .= " AND {$term_relationships}.term_taxonomy_id IN ({$cat_ids}) ".PHP_EOL;
      $where .= " AND {$term_taxonomy}.term_id IN ({$cat_ids}) ".PHP_EOL;
    }
    //除外カテゴリー指定
    if (is_ids_exist($exclude_cat_ids)) {
      //空の配列を取り除く
      $exclude_cat_ids = array_filter($exclude_cat_ids, "strlen");
      //カンマ区切りにする
      $ex_cat_ids = implode(',', $exclude_cat_ids);
      $ex_cat_ids = preg_replace('/,$/', '', $ex_cat_ids);
      $where .= " AND {$term_relationships}.term_taxonomy_id NOT IN ({$ex_cat_ids}) ".PHP_EOL;
    }

    $where .= " AND {$term_taxonomy}.taxonomy = 'category' ".PHP_EOL;
    // //テーブル結合するクエリの場合はWHEREに付け加えるのでANDに変更する
    // $where = str_replace('WHERE', 'AND', $where);
    $query = "
      SELECT {$joined_table}.post_id, SUM({$joined_table}.count) AS sum_count, {$joined_table}.term_taxonomy_id, {$joined_table}.taxonomy
        FROM (
          #カテゴリとアクセステーブルを内部結合してグルーピングし並び替えた結果
          SELECT {$access_table}.post_id, {$access_table}.count, {$term_relationships}.term_taxonomy_id, {$term_taxonomy}.taxonomy
            FROM {$term_relationships}
            INNER JOIN {$access_table} ON {$term_relationships}.object_id = {$access_table}.post_id
            INNER JOIN {$term_taxonomy} ON {$term_relationships}.term_taxonomy_id = {$term_taxonomy}.term_taxonomy_id
            $where #WHERE句
            GROUP BY {$access_table}.id
        ) AS {$joined_table} #カテゴリとアクセステーブルを内部結合した仮の名前
        GROUP BY {$joined_table}.post_id
        ORDER BY sum_count DESC
    ";
    //_v($query);
    //1回のクエリで投稿データを取り出せるようにテーブル結合クエリを追加
    $query = wrap_joined_wp_posts_query($query, $limit, $author, $post_type);
  } else {
    $query = "
      SELECT {$access_table}.post_id, SUM({$access_table}.count) AS sum_count
        FROM {$access_table} $where
        GROUP BY {$access_table}.post_id
        ORDER BY sum_count DESC
    ";
    //1回のクエリで投稿データを取り出せるようにテーブル結合クエリを追加
    $query = wrap_joined_wp_posts_query($query, $limit, $author, $post_type);
  }

  $records = $wpdb->get_results( $query );
  
  if (is_access_count_cache_enable() && $records) {
    set_transient( $transient_id, $records, 60 * get_access_count_cache_interval() );
  }
  return $records;
}
endif;

3. 改造したポイント

人気記事ショートコードを生成するコードをもとに、急上昇記事ランキングになるようにSQLクエリの部分を改造しました。

//急上昇ランキングリストの取得
/** lib/html-forms.php */
if ( !function_exists( 'generate_trend_entries_tag' ) ):
function generate_trend_entries_tag($atts){
  extract(shortcode_atts(array(
    'days' => 'all',
    'entry_count' => 5,
    'entry_type' => ET_DEFAULT,
    'ranking_visible' => 0,
    'pv_visible' => 0,
    'cat_ids' => array(),
    'children' => 0,
    'exclude_post_ids' => array(),
    'exclude_cat_ids' => array(),
    'bold' => 0,
    'arrow' => 0,
    'class' => null,
    'author' => null,
    'post_type' => 'post',
    'horizontal' => 0,
  ), $atts));

  $records = get_trend_ranking_records($days, $entry_count, $entry_type, $cat_ids, $exclude_post_ids, $exclude_cat_ids, $children, $author, $post_type);

  $thumb_size = get_popular_entries_thumbnail_size($entry_type);
  $atts = array(
    'type' => $entry_type,
    'ranking_visible' => $ranking_visible,
    'pv_visible' => $pv_visible,
    'bold' => $bold,
    'arrow' => $arrow,
    'class' => $class,
    'horizontal' => $horizontal,
  );
  $cards_classes = get_additional_widget_entry_cards_classes($atts);
  ?>
  <div class="popular-entry-cards widget-entry-cards no-icon cf<?php echo $cards_classes; ?>">
  <?php if ( $records ) :
    $i = 1;
    foreach ($records as $post):
      $permalink = get_permalink( $post->ID );
      $title = $post->post_title;
      $no_thumbnail_url = ($entry_type == ET_DEFAULT) ? get_no_image_120x68_url($post->ID) : get_no_image_320x180_url($post->ID);
      $w   = ($entry_type == ET_DEFAULT) ? THUMB120WIDTH  : THUMB320WIDTH;
      $h   = ($entry_type == ET_DEFAULT) ? THUMB120HEIGHT : THUMB320HEIGHT;

      $post_thumbnail = get_the_post_thumbnail( $post->ID, $thumb_size, array('alt' => '', 'loading' => 'lazy', 'decoding' => 'async') );
      $pv = $post->sum_count;

      if ($post_thumbnail) {
        $post_thumbnail_img = $post_thumbnail;
      } else {
        $post_thumbnail_img = get_original_image_tag($no_thumbnail_url, $w, $h, 'no-image popular-entry-card-thumb-no-image widget-entry-card-thumb-no-image', '');
      }

      $pv_tag = null;
      if ($pv_visible){
        $pv_text = $pv == '1' ? $pv.' view' : $pv.' views';
        $pv_tag = '<span class="popular-entry-card-pv widget-entry-card-pv">'.$pv_text.'</span>';
      }
      ?>
  <a href="<?php echo $permalink; ?>" class="popular-entry-card-link widget-entry-card-link a-wrap no-<?php echo $i; ?>" title="<?php echo esc_attr($title); ?>">
    <div class="popular-entry-card widget-entry-card e-card cf">
      <figure class="popular-entry-card-thumb widget-entry-card-thumb card-thumb">
        <?php echo $post_thumbnail_img; ?>
        <?php
        $is_visible = apply_filters('is_popular_entry_card_category_label_visible', false);
        $is_visible = apply_filters('is_widget_entry_card_category_label_visible', $is_visible);
        the_nolink_category($post->ID, $is_visible); //カテゴリラベルの取得 ?>
      </figure><!-- /.popular-entry-card-thumb -->

      <div class="popular-entry-card-content widget-entry-card-content card-content">
        <span class="popular-entry-card-title widget-entry-card-title card-title"><?php echo $title;?></span>
        <?php if ($entry_type != ET_LARGE_THUMB_ON): ?>
          <?php echo $pv_tag; ?>
        <?php endif ?>
        <?php generate_widget_entry_card_date('popular', $post->ID); ?>
      </div><!-- /.popular-entry-content -->
      <?php if ($entry_type == ET_LARGE_THUMB_ON): ?>
        <?php echo $pv_tag; ?>
      <?php endif ?>
    </div><!-- /.popular-entry-card -->
  </a><!-- /.popular-entry-card-link -->

  <?php
  $i++;
  endforeach;
  else :
    echo '<p>'.__( '人気記事は見つかりませんでした。', THEME_NAME ).'</p>';//見つからない時のメッセージ
  endif; ?>
  </div>
<?php
}
endif;


/** lib/page-access/access-func.php */

//アクセスランキングを取得
if ( !function_exists( 'get_trend_ranking_records' ) ):
function get_trend_ranking_records($days = 'all', $limit = 5, $type = ET_DEFAULT, $cat_ids = array(), $exclude_post_ids = array(), $exclude_cat_ids = array(), $children = 0, $author = null, $post_type = 'post'){
  //カテゴリー配列を文字列に変換
  $cat_ids = is_array($cat_ids) ? $cat_ids : array();
  $cats = implode(',', $cat_ids);
  
  //アクセスキャッシュを有効にしている場合
  if (is_access_count_cache_enable()) {
    if ($cat_ids) {
      //子孫カテゴリも含める場合
      if ($children) {
        $categories = $cat_ids;
        $res = $categories;
        foreach ($categories as $category) {
          $res = array_merge($res, get_term_children( $category, 'category' ));
        }
        $cat_ids = $res;
        $cats = implode(',', $res);
      }
    }

    //除外投稿
    $archive_exclude_post_ids = get_archive_exclude_post_ids();
    if ($archive_exclude_post_ids && is_array($archive_exclude_post_ids)) {
      $exclude_post_ids = array_unique(array_merge($exclude_post_ids, $archive_exclude_post_ids));
    }

    $exclude_post_ids = is_array($exclude_post_ids) ? $exclude_post_ids : array();
    $expids = implode(',', $exclude_post_ids);
    $exclude_cat_ids = is_array($exclude_cat_ids) ? $exclude_cat_ids : array();
    $excats = implode(',', $exclude_cat_ids);
    $type = get_accesses_post_type();
    $transient_id = TRANSIENT_POPULAR_PREFIX.'?days='.$days.'&limit='.$limit.'&type='.$type.'&cats='.$cats.'&children='.$children.'&expids='.$expids.'&excats='.$excats.'&author='.$author.'&post_type='.$post_type;
    
    $cache = get_transient( $transient_id );
    if ($cache) {
      if (DEBUG_MODE && is_user_administrator()) {
        // echo('<pre>');
        // echo $transient_id;
        // echo('</pre>');
      } elseif (is_user_administrator()){

      } else {
        return $cache;
      }
    }
  }



  global $wpdb;
  $trend_table = ACCESSES_TABLE_NAME;
  // $post_type = 'post';
  $date = get_current_db_date();
  $date_yesterday = get_current_db_date_before(1);

  $where = " WHERE {$trend_table}.post_type = '$post_type' ".PHP_EOL;
  // _v($where);
  if ($days != 'all') {
    $date_before = get_current_db_date_before($days);
    $where .= " AND {$trend_table}.date BETWEEN '$date_before' AND '$date' ".PHP_EOL;
  }

  if (is_ids_exist($exclude_post_ids)) {
    $where .= " AND {$trend_table}.post_id NOT IN(".implode(',', $exclude_post_ids).") ".PHP_EOL;
  }
  //3180, 3234
  if (!is_numeric($limit)) {
    $limit = 5;
  }
  //カテゴリを指定する場合
  if (is_ids_exist($cat_ids) || is_ids_exist($exclude_cat_ids)) {
    global $post;
    $term_relationships = $wpdb->term_relationships;
    $term_taxonomy = $wpdb->term_taxonomy;
    $joined_table = 'terms_accesses';
    //カテゴリー指定
    if (is_ids_exist($cat_ids)) {
      $cat_ids = implode(',', $cat_ids);
      //$where .= " AND {$term_relationships}.term_taxonomy_id IN ({$cat_ids}) ".PHP_EOL;
      $where .= " AND {$term_taxonomy}.term_id IN ({$cat_ids}) ".PHP_EOL;
    }
    //除外カテゴリー指定
    if (is_ids_exist($exclude_cat_ids)) {
      //空の配列を取り除く
      $exclude_cat_ids = array_filter($exclude_cat_ids, "strlen");
      //カンマ区切りにする
      $ex_cat_ids = implode(',', $exclude_cat_ids);
      $ex_cat_ids = preg_replace('/,$/', '', $ex_cat_ids);
      $where .= " AND {$term_relationships}.term_taxonomy_id NOT IN ({$ex_cat_ids}) ".PHP_EOL;
    }

    $where .= " AND {$term_taxonomy}.taxonomy = 'category' ".PHP_EOL;
    // //テーブル結合するクエリの場合はWHEREに付け加えるのでANDに変更する
    // $where = str_replace('WHERE', 'AND', $where);
    $query = "
      SELECT {$joined_table}.post_id, SUM({$joined_table}.count) AS sum_count, {$joined_table}.term_taxonomy_id, {$joined_table}.taxonomy
        FROM (
          #カテゴリとアクセステーブルを内部結合してグルーピングし並び替えた結果
          SELECT {$trend_table}.post_id, {$trend_table}.count, {$term_relationships}.term_taxonomy_id, {$term_taxonomy}.taxonomy
            FROM {$term_relationships}
            INNER JOIN {$trend_table} ON {$term_relationships}.object_id = {$trend_table}.post_id
            INNER JOIN {$term_taxonomy} ON {$term_relationships}.term_taxonomy_id = {$term_taxonomy}.term_taxonomy_id
            $where #WHERE句
            GROUP BY {$trend_table}.id
        ) AS {$joined_table} #カテゴリとアクセステーブルを内部結合した仮の名前
        GROUP BY {$joined_table}.post_id
        ORDER BY sum_count DESC
    ";
    //_v($query);
    //1回のクエリで投稿データを取り出せるようにテーブル結合クエリを追加
    $query = wrap_joined_wp_posts_query($query, $limit, $author, $post_type);
  } else {

	  
    $query = "
	
SELECT t1.post_id, 
  ROUND((t2.today) / 1.5 - (t1.latest - t2.today) /  ($days - 2))  AS sum_count
FROM (
	SELECT {$trend_table}.post_id, 
	  SUM({$trend_table}.count) AS latest
	FROM {$trend_table}
	WHERE {$trend_table}.post_type = '$post_type'
	  AND {$trend_table}.date BETWEEN '$date_before' AND '$date' 
	GROUP BY {$trend_table}.post_id
) t1 INNER JOIN (
	SELECT {$trend_table}.post_id, 
	  SUM({$trend_table}.count) AS today
	FROM {$trend_table}
	WHERE {$trend_table}.post_type = '$post_type'
	  AND {$trend_table}.date BETWEEN '$date_yesterday' AND '$date' 
	GROUP BY {$trend_table}.post_id
) t2
  ON t1.post_id = t2.post_id
ORDER BY  sum_count DESC

	";
    //1回のクエリで投稿データを取り出せるようにテーブル結合クエリを追加
    $query = wrap_joined_wp_posts_query($query, $limit, $author, $post_type);
  }

  $records = $wpdb->get_results( $query );
  
  if (is_access_count_cache_enable() && $records) {
    set_transient( $transient_id, $records, 60 * get_access_count_cache_interval() );
  }
  return $records;
}
endif;
改造したポイント

SQLの部分だけを変更できればよいのですが、関数パラメータになっているわけではないので、まるごとコピーしてから、別の関数にしました。

その分、保守性は悪くなってしまいますね。

今後のために、改造した箇所(主に3つ)をメモしておきます。

3-1. 関数・変数名の変更

既存のコードは衝突しないように、複製したコードの変更名を変更しました。
(popular_list → trend_list、access_table → trend_table など)。

単純な検索・置換だと、呼び出している関数がおかしくなることがあるので、確認しながら操作しました。

3-2. クエリ用に変数を追加した

急上昇ランキングでは、直近のアクセスと最近のアクセスの平均を比べて、増えているページを上位にしています。

クエリ用に変数を追加した

安定してアクセスが多いページではなく、急にアクセスが増えたページを見たいからです。

急にアクセス数が増えたページは、検索エンジンに評価されたか、検索数が増えたか、しているので、なんらかの需要があります。検索理由に合っているか検証して、優先的にページ内容を見直しています。

直近のアクセスを集計するために、get_trend_ranking_records関数に、変数$day_yesterdayを追加しました。

            $date_yesterday = get_current_db_date_before(1);
クエリ用に変数を追加した

$day_beforeがある辺りです。

3-3. 集計クエリを変更する

get_trend_ranking_records関数の$queryの中身を変更しました。
これがメインの部分です。

この際、最近1週間(期間は変更可能)の平均よりどれぐらいアクセスが増えているかに対応するように計算式を改めました。

計算式

カウント = 前日・当日のアクセス / 1.5 – (最近のアクセス – 前日・当日のアクセス) / (集計期間 – 2)

当日のアクセスは、時間によって重み付けが変わる必要がありますが、0.5日分として決め打ちしています。

    $query = "
	
SELECT t1.post_id, 
  ROUND((t2.today) / 1.5 - (t1.latest - t2.today) /  ($days - 2))  AS sum_count
FROM (
	SELECT {$trend_table}.post_id, 
	  SUM({$trend_table}.count) AS latest
	FROM {$trend_table}
	WHERE {$trend_table}.post_type = '$post_type'
	  AND {$trend_table}.date BETWEEN '$date_before' AND '$date' 
	GROUP BY {$trend_table}.post_id
) t1 INNER JOIN (
	SELECT {$trend_table}.post_id, 
	  SUM({$trend_table}.count) AS today
	FROM {$trend_table}
	WHERE {$trend_table}.post_type = '$post_type'
	  AND {$trend_table}.date BETWEEN '$date_yesterday' AND '$date' 
	GROUP BY {$trend_table}.post_id
) t2
  ON t1.post_id = t2.post_id
ORDER BY  sum_count DESC

	";

最近の集計(t2)と、当日・前日の集計(t1)を結合して、sum_countを集計しています。

無事に修正できました。

集計クエリを変更する

こちらもどうぞ。

Cocoonで注目記事ランキングのショートコードを作成した【SQLって何?からのデータベース操作】
Cocoonで注目記事ランキングのショートコードを作成した【SQLって何?からのデータベース操作】
記事のアクセスランキング(人気記事)は、なかなか上位の記事が変わらない傾向があります。 そこで、WordPressの記事のアクセス数の前週比のランキング(急上昇の記事)を作りたいと思いました。 Cocoonのコードを読んでみるとアクセスランキングは、SQLクエリで生成されていました。 完成したもの Cocoonのget_access_ranking_recordsのSQLクエリ Cocoonのアクセスランキングは、「lib/page-access/access-func.ph...
WordPressのテンプレートをいじらずにPHPコードで遊びたい【テキストウィジェットで評価】
WordPressのテンプレートをいじらずにPHPコードで遊びたい【テキストウィジェットで評価】
WordPressのカスタマイズにはPHPコードを利用しますが、テンプレートをいじるのはなんか不安です。 ウィジェットとしてPHPコードを実行したいと思います。 追記(2024-07-20) 任意のPHPコードを評価する機能は、セキュリティリスクが大きいので削除しました。 カスタムHTMLではPHPコードは実行できない まず試したのがウィジェットの「カスタムHTML」です。 しかし、「<?」で始まるタグはエラーになってしまいます。 Special characters mus...
[WordPress] カテゴリーが更新されない?
[WordPress] カテゴリーが更新されない?
WordPressで記事のカテゴリーを増やしたら、投稿パネルの「カテゴリー」が更新されない、というケースがありました。 カテゴリーを増やした別のPCからログインして、記事を編集しようとすると、記事編集画面のカテゴリーが以前のままなのです。カテゴリーの追加が反映されていません。 設定から「カテゴリー」を表示すると、正しく表示されるのですが……どうもブラウザ(Chrome)にキャッシュが残っているようです。 記事編集画面を更新しても戻りません。 そこで、Chromeの設定から「C...
QRコードを読み込むと、関連記事を確認できます。

Cocoonで作った注目記事ランキングのショートコードを修正した
【スポンサーリンク】
タイトルとURLをコピーしました