自作プラグインが動かなくなった原因は、サーバー処理のメモリ不足でした。
$posts = get_posts( array(
'post_type' => 'post',
'post_status' => array( 'publish', 'pending', 'draft', 'future'),
'orderby' => 'modified', /* date, modified */
'numberposts' => -1
) );
$count = 0;
foreach ( $posts as $post ) {
$count += post_word_count($post->post_content);
}
get_posts関数で、全記事の文字数を計算するときに、メモリ不足になっていました。
get_postsのメモリ管理が変わったのか、記事数が増えたことが原因なのかはわかりません。
そこで、バッチ処理に分割して、文字数を合計していくように変更しました。
/** メモリ消費を抑えるために、以下のようにバッチ処理を実装 */
function calc_total_post_characters() {
global $wpdb;
$total_count = 0;
$batch_size = 100; // 一度に処理する投稿数
$offset = 0;
do {
$query = $wpdb->prepare(
"SELECT ID, post_content
FROM {$wpdb->posts}
WHERE post_type = %s
AND post_status IN (%s, %s, %s, %s)
ORDER BY ID
LIMIT %d OFFSET %d",
'post',
'publish',
'pending',
'draft',
'future',
$batch_size,
$offset
);
$posts = $wpdb->get_results($query);
foreach ($posts as $post) {
$total_count += post_word_count($post->post_content);
}
$offset += $batch_size;
// メモリをクリア
wp_cache_flush();
if (function_exists('opcache_reset')) {
opcache_reset();
}
} while (count($posts) == $batch_size);
return $total_count;
}
そのほか、変数の定義やエラーチェックを見直しました。
1. 自作プラグインが表示されない
WordPressを開いたら、カスタムプラグインが動作しなくなっていました。
ちょうど最近 WordPress 6.6になったからか、PHP 8.2に上がっていたからか、原因がわかりませんが、プラグインの動作の修正が必要なようです。
1-1. WordPressとPHPのエラーメッセージ
WordPressのデバッグモードを有効にする1と、エラーメッセージが出て来ました。
- Warning:
Constant ACCESSES_TABLE_NAME already defined
in access-func.php - Warning:
Cannot modify header information
– headers already sent by (output started at access-func.php:12)
in misc.php on line 1438 - Warning:
Cannot modify header information
– headers already sent by (output started at access-func.php:12)
in functions.php on line 7108 - Warning:
Cannot modify header information
– headers already sent by (output started at access-func.php:12)
in admin-header.php on line 9 - Warning:
Undefined variable $row
in chiilabo-stats-main.php on line 376 - Warning:
Undefined variable $row
in chiilabo-stats-main.php on line 376 - Fatal error:
Allowed memory size of 268435456 bytes exhausted
(tried to allocate 20480 bytes)
in meta.php on line 1180
Warning: Constant ACCESSES_TABLE_NAME already defined in /home/[username]/public_html/chiilabo.co.jp/wp-content/themes/cocoon-master/lib/page-access/access-func.php on line 12
Warning: Cannot modify header information - headers already sent by (output started at /home/[username]/public_html/chiilabo.co.jp/wp-content/themes/cocoon-master/lib/page-access/access-func.php:12) in /home/[username]/public_html/chiilabo.co.jp/wp-admin/includes/misc.php on line 1438
Warning: Cannot modify header information - headers already sent by (output started at /home/[username]/public_html/chiilabo.co.jp/wp-content/themes/cocoon-master/lib/page-access/access-func.php:12) in /home/[username]/public_html/chiilabo.co.jp/wp-includes/functions.php on line 7108
Warning: Cannot modify header information - headers already sent by (output started at /home/[username]/public_html/chiilabo.co.jp/wp-content/themes/cocoon-master/lib/page-access/access-func.php:12) in /home/[username]/public_html/chiilabo.co.jp/wp-admin/admin-header.php on line 9
Warning: Undefined variable $row in /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php on line 376
Warning: Undefined variable $row in /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php on line 380
Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /home/[username]/public_html/chiilabo.co.jp/wp-includes/meta.php on line 1180
このサイトで重大なエラーが発生しました。対応手順については、サイト管理者のメール受信ボックスを確認してください。
メールでもPHPエラーが届いていました。
PHPのスクリプトエンジンが出力するエラーは、メールで送る設定になっています。
- Uncaught ArgumentCountError:
Too few arguments to function echo_grid_stats_display_style(),
0 passed
in chiilabo-stats-main.php on line 553
and exactly 1 expected
in chiilabo-stats-main.php:368
エラー詳細
===============
エラータイプ E_ERROR が /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php ファイルの 368 行目で発生しました。
エラーメッセージ: Uncaught ArgumentCountError: Too few arguments to function echo_grid_stats_display_style(), 0 passed in /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php on line 553 and exactly 1 expected in /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php:368
Stack trace:
#0 /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php(553): echo_grid_stats_display_style()
#1 /home/[username]/public_html/chiilabo.co.jp/wp-content/plugins/chiilabo-stats/chiilabo-stats-main.php(358): grid_stats_display_inner(180)
#2 /home/[username]/public_html/chiilabo.co.jp/wp-includes/class-wp-hook.php(324): grid_stats_display('')
#3 /home/[username]/public_html/chiilabo.co.jp/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters('', Array)
#4 /home/[username]/public_html/chiilabo.co.jp/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#5 /home/[username]/public_html/chiilabo.co.jp/wp-admin/admin.php(259): do_action('%e3%81%a1%e3%81...')
#6 {main}
thrown
ただし、WP_DEBUGがオンのままだと、サイト訪問者にも表示されてしまいます。
エラーメッセージを確認したら、そのつど すぐにオフに戻しました。
1-2. エラーメッセージの概要
コードの不注意に対する警告とメモリ不足のエラーがありました。
- 定数の重複定義
ACCESSES_TABLE_NAMEという定数が二度定義されているという警告が出ています。 - 未定義の変数
$rowという変数が定義されていないという警告が2回出ています。 - ヘッダー情報の変更エラー
ヘッダー情報を変更できないという警告が3回出ています。
これはそれ以外の問題による二次的な問題で、ウェブページの内容を出力し始めた後で、ヘッダーにメッセージを出力しようとしたために起こっています。 - メモリ不足エラー
プログラムが使用できるメモリの上限を超えてしまったという重大なエラーが発生しています。
いろんなファイルで警告が表示されていますが、自分が関係しているコードは chiilabo-stats-main.php と functions.php に限られています。
警告やエラーの示す場所にかかわらず、原因はその中にありそうです。
2. chiilabo-stats-main.phpの修正
このコードは、自分で追加したカスタムプラグインです。
2-1. 【修正】ACCESSES_TABLE_NAMEの再定義
まずは、ACCESSES_TABLE_NAME
の問題を検証します。
最初のエラーは、ACCESSES_TABLE_NAME という定数が既に定義されているにも関わらず、再度定義しようとしていることを示しています。
(/wp-content/themes/cocoon-master/lib/page-access/access-func.php
ファイルの12行目)
しかし、Cocoonテーマではなく、自分のカスタムプラグインの問題です。
というのも、chiilabo-stats-main.php には、確かに ACCESSES_TABLE_NAME
を定義する箇所が含まているからです。
if (!defined('ACCESSES_TABLE_NAME')) {
define( 'ACCESSES_TABLE_NAME', $wpdb->prefix . 'cocoon' . '_accesses' );
}
これは、Cocoonテーマで記録したアクセスログを元に記事分析をしているためです。
再定義しないように気を付けてはいたのですが、「wp-content/themes/cocoon-master/lib/page-access/access-func.php」の方でエラーになっていました。
読み込み順がプラグインの方がCocoonテーマより前になっているのでしょう。
そこで、access-func.phpと定数名が競合しないように、chiilabo-stats-main.php内の定数を「COCOON_ACCESSES_TABLE_NAME」という別名に変更しました。
2-2. 【修正】リファクタリングのミス
次のエラーは、$rowの変数。
chiilabo-stats-main.php
ファイルで $row 変数が使用される前に定義されていません。
これは、コードを整理するときにミスしていたことが原因でした。
関数の一部を別の関数に抜き出したときに、ローカル変数を含めたままだったのです。
ローカル変数は、パラメータとして渡すように修正しました。
これらの問題を修正すると同時に、ヘッダー情報の変更エラーも解消しました。
WordPressエラーの出力(echo文やHTMLなど)が、header()関数やセッション開始前に行われていたことが問題だったからです。
2-3. 【修正】Allowed memory size of 〜 bytes exhausted (get_posts)
残る問題が一番大きな問題です。
集計の表示で「致命的なエラー」になって停止してしまっているのです。
致命的なエラー: 許可されたメモリ サイズ 268435456 バイトを使い果たしました (20480 バイトを割り当てようとしました)
268435456 バイトは 256 MB に相当します。
スクリプトがさらに20480バイト(20 KB)のメモリを割り当てようとしたところで、限度に達していたためエラーが発生したようです。
wp-config.php
ファイルに define('WP_MEMORY_LIMIT', '512M');
を追加するなど、メモリ制限を増やしてみたものの効果はありませんでした。
コード内にデバッグ出力を入れて、動作が停止している箇所を特定します。
すると、get_posts 関数で停止してしまっていることがわかりました。
function add_count_to_db() {
$posts = get_posts( array(
'post_type' => 'post',
'post_status' => array( 'publish', 'pending', 'draft', 'future'),
'orderby' => 'modified', /* date, modified */
'numberposts' => -1
) );
$count = 0;
foreach ( $posts as $post ) {
$count += post_word_count($post->post_content);
}
//...
全記事の内容をまとめて取得する処理がメモリオーバーになっていたようです。
処理が遅いとは思っていたけど、今まで大丈夫だったのにね……
そこで、全記事の合計文字数を計算する処理を関数に分けて、100件ずつ取得して計算するように修正しました。
/** メモリ消費を抑えるために、以下のようにバッチ処理を実装 */
function calc_total_post_characters() {
global $wpdb;
$total_count = 0;
$batch_size = 100; // 一度に処理する投稿数
$offset = 0;
do {
$query = $wpdb->prepare(
"SELECT ID, post_content
FROM {$wpdb->posts}
WHERE post_type = %s
AND post_status IN (%s, %s, %s, %s)
ORDER BY ID
LIMIT %d OFFSET %d",
'post',
'publish',
'pending',
'draft',
'future',
$batch_size,
$offset
);
$posts = $wpdb->get_results($query);
foreach ($posts as $post) {
$total_count += post_word_count($post->post_content);
}
$offset += $batch_size;
// メモリをクリア
wp_cache_flush();
if (function_exists('opcache_reset')) {
opcache_reset();
}
} while (count($posts) == $batch_size);
return $total_count;
}
function add_count_to_db() {
$count = calc_total_post_characters();
//...
3. functions.phpの見直し
一応、functions.phpについてもコードの問題点を検証しました。
3-1. 【廃止】PHPコードを実行するウィジェットwidget_text_exec_php
functions.phpに追加していた関数 widget_text_exec_php で出力バッファリングを使用していました。
/**
* プラグインなしでPHPコードを実行する方法
*/
function widget_text_exec_php( $widget_text ) {
if( strpos( $widget_text, '<' . '?' ) !== false ) {
ob_start();
eval( '?>' . $widget_text );
$widget_text = ob_get_contents();
ob_end_clean();
}
return $widget_text;
}
add_filter( 'widget_text', 'widget_text_exec_php', 99 );
この関数は、テキストウィジェットの表示前に実行され、テキストにPHPコードが含まれていれば、そのコードを評価(実行)した結果に置き換えて表示します。
しかし、eval()関数はセキュリティリスクが大きいです。
eval()
関数の使用:
PHP 8.2に限らず、eval()
の使用は非常に危険です。
任意のPHPコードが実行される可能性があるからです。- 非推奨の関数
strpos()
:
PHP 8.2では、strpos()
関数の代わりにstr_contains()
の使用が推奨されています。 - 出力バッファリング
ob_start()
とob_end_clean()
:ob_start()
とob_end_clean()
の使用は、予期しない副作用を引き起こす可能性があります。
今は、ウィジェットテキストでPHPコードを使っていなかったので、丸ごと削除することにしました。
3-2. 【検討】アクセスランキング取得関数 get_trend_ranking_recordsの処理
関数 get_trend_ranking_records 内でもデータベースクエリを実行しています。
これも、メモリ使用量が多くなる可能性があります。
以下のようなショートコードのための関数です。
if (!shortcode_exists('trend_list')) {
add_shortcode('trend_list', 'trend_entries_shortcode');
}
このコードでは、Cocoonのアクセスランキングの関数の処理の最深部にあるSQLクエリだけを自分で指定しています。
$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
このクエリを使って記事リストを表示するためだけに、アクセスランキングのコード全体を複製しています。
このクエリでは、単純な全期間のアクセス数だけでなく、最近のトレンドも考慮に入れた人気度を計算しようとしています。
最近アクセスが増えている投稿は、全体的なアクセス数が少なくても上位に来る可能性があります。
function trend_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, 'trend_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_trend_entries_tag($atts);
$res = ob_get_clean();
return $res;
}
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
}
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 {
// ROUND((t2.today)- (t1.latest - t2.today) / ($days - 2)) AS sum_count
$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;
もう少し短いコードで解決できそうですが、今回は見送りです。