お問い合わせ

SWELLの投稿リストブロックをキャッシュ付きにするカスタマイズ

SWELLの投稿リストブロックは多機能で便利です。

便利だからといって、TOPページで投稿リストブロックをカテゴリごとに分けて複数配置している人も多いと思います。

投稿リストブロックは一つのブロックごとにクエリを発行しますので、複数配置かつ記事の数が多くなってくるとページ表示速度が遅くなる欠点があります。

この記事では、SWELLの投稿リストをキャッシュ付きにするカスタマイズをご紹介します。

このカスタマイズは、投稿リストのショートコード[post_list]にも有効です。

この記事の内容

投稿リストブロックが記事一覧を表示するまでの流れ

投稿リストブロックはサブループで実行される

WordPressで記事一覧を取得する場合、クエリを発行して取得しますが、メインループとサブループの場合で処理方法が異なります。

SWELLの投稿リストブロックは、メインループになるアーカイブページと異なりサブループの処理になります。

投稿リストブロックの処理フロー

投稿リストブロックは、パラメータを取得してサブループを回します。

  1. パラメータを引数にしてlist_on_block()関数を呼び出す。
  2. list_on_block()関数内部で、parts/post_list/loop_subを呼び出し、サブループを実行する。
  3. parts/post_list/loop_subがHTMLを出力する

この流れの中でキャッシュすべきは、3の部分です。

パラメータごとに結果はユニークなはずですからパラメータをキーにしてキャッシュを生成して、キャッシュを読み込む処理を追加します。

クエリの発行時間が少なくなれば、処理速度が速くなり、ページ表示も高速になります。

キャッシュ付きのサブループを実装する

parts/post_list/loop_subのファイルは子テーマでカスタマイズ可能ですから、parts/post_list/loop_subをカスタマイズすればキャッシュ付きのサブループを実装できます。

ブロックエディタにブロックを配置した時に、キャッシュを読み込まないように判定しています。

ブロックエディタ表示時は、キャッシュスルーにしたいのですが、is_admin()などの判定が効きません。

以下の記事にブロックエディタを開いていることを判定する方法があったのでそれを使っています。

<?php
use \SWELL_THEME\Parts\Post_List;
if ( ! defined( 'ABSPATH' ) ) exit;


if( is_admin() || (defined( 'REST_REQUEST' ) && REST_REQUEST && 'edit' === $_GET['context'])) {
	$cache_bypass = 1;
}else{
	$cache_bypass = 0;
}
/**
 * サブループでの投稿リスト出力テンプレート
 */
if ( isset( $variable['query'] ) ) {
	
	$transient_key =  'sub_loop_'.md5(serialize($variable['query']));
	$res = get_transient($transient_key);
	if($res===false || $cache_bypass ):
		// すでにクエリが生成済みの場合
		$the_query = $variable['query'];
	endif;
} elseif ( isset( $variable['query_args'] ) ) {

	$transient_key =  'sub_loop_'.md5(serialize($variable['query_args']));
	$res = get_transient($transient_key);
	if(( $res===false || $cache_bypass) || !empty($variable['list_args']['cacheoff'])):
		// クエリ生成
		$the_query = new \WP_Query( $variable['query_args'] );
	endif;
} else {
	// クエリに関する情報がない時
	return;
}
if($res!==false && !$cache_bypass){
	echo $res."<!-- cached -->";
	return;
}
ob_start();

// リストの設定情報
$list_args = isset( $variable['list_args'] ) ? $variable['list_args'] : [];

// リストデータ整理
$list_data = Post_List::get_list_data( $list_args );

$li_args         = $list_data['li_args'];
$ul_class        = $list_data['ul_class'];
$parts_name      = $list_data['parts_name'];
$infeed_interval = $list_data['infeed_interval'];


// 記事がなかった場合
if ( ! $the_query->have_posts() ) :
	$not_founded_text = __( '記事が見つかりませんでした。', 'swell' );
	// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	echo apply_filters( 'swell_posts_404_text', '<p>' . $not_founded_text . '</p>' );
	return;
endif;


// ループ
$loop_ct = 0;
echo '<ul class="' . esc_attr( $ul_class ) . '">';
while ( $the_query->have_posts() ) :
	$the_query->the_post();

	// インフィード
	if ( $infeed_interval && $loop_ct && ( 0 === $loop_ct % $infeed_interval ) ) :
		SWELL_Theme::get_parts( 'parts/post_list/infeed_ad', $loop_ct );
		endif;

	SWELL_Theme::get_parts( 'parts/post_list/' . $parts_name, $li_args );

	$loop_ct++;
endwhile;
echo '</ul>';

$res = ob_get_clean();
if(!$cache_bypass):
set_transient(
	$transient_key,
	$res,
	60 * 60 * 24 * 7//秒で指定(サンプルは一日)
);
endif;
echo $res;

wp_reset_postdata();

キャッシュ削除の処理

記事を更新した時にキャッシュを削除する処理をしないと、transientの期限まで更新されなくなります。

add_action( 'save_post', 'wpdocs_delete_my_important_transient',9,1);
add_action( 'deleted_post', 'wpdocs_delete_my_important_transient',9,1 );
//add_action( 'edit_post', 'wpdocs_delete_my_important_transient',9,3 );
function wpdocs_delete_my_important_transient($post_ID) {
	$prefix="sub_loop_";
	delete_transient_prefix($prefix);
	
}

function delete_transient_all(){
	global $wpdb;
	$db_prefix = $wpdb->prefix;
	$wpdb->query("delete from `".$db_prefix."options` where `option_name` like '%_transient_%'");	
}

function delete_transient_prefix($prefix){
	global $wpdb;
	$db_prefix = $wpdb->prefix;
	$wpdb->query("delete from `".$db_prefix."options` where `option_name` like '%_transient_".$prefix."_%'");	
}

まとめ

今回のカスタマイズは、サブループを使っている他の機能でも同様にキャッシュされるので、投稿リストブロックだけではなく、投稿リストのショートコードに対しても有効です。

何でもかんでもキャッシュしてしまうので、問題が起きることも考えられます。

適用する場合は、自己責任でよろしくお願いします。

役に立ったら他の人にもシェア!
  • URLをコピーしました!
  • URLをコピーしました!
コメントを閉じる

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

この記事の内容