ワードプレスプログラミング 100行で簡単なキャッシュプラグインを作成してみる

この記事でデータベースにキャッシュデータを保存してページの表示ごとにそのデータからページを出力する簡単なキャッシュプラグインを作ってまいりましょう。

ローカルコンピューターでテストサイトを作って制作を行うとプログラムの修正、動作確認がとても楽になります。

1 プラグインのファイルを作る

まずテキストエディターで下記のコードをコピペして任意の名称で保存して、ワードプレスのwp-content/pluginsフォルダに配置してください。

<?php
/*
Plugin Name: 簡単なキャッシュプラグイン
Plugin URI: http://example.cpm/
Description: とても簡単なキャッシュプラグインです
Version: 1.0
Author: テスト製作者
Author URI: https://example.cpm/
*/

?>

/*~*/まではコメントと呼ばれ、プログラム上は何ら処理されない部分ですが、ワードプレスはプラグインフォルダにあるファイルのこのコメント部分からプラグイン情報を読み取ります。
ゆえに、このコメント部分にお好きな設定を書き込まれてオリジナルなプラグインを作ることができます。

管理画面のプラグイン一覧画面に行くと、「簡単なキャッシュプラグイン」というプラグインが認識されているかと存じます。有効にされても現状は何の機能も書かれていませんので現状は何も起こりません。

※これ以降のコードは順番にプロフラムに追記されることでプラグインができていきます。

2 キャッシュプラグイン用のデータベースのテーブルを作る

プラグインで使う、キャッシュ用のデータベースを作りましょう。このデータベースを作るタイミングはプラグインを有効にした時が最適かと思います。

function fcashdata_dbinstall() {
    global $wpdb;
    $fcashdata_db_version= '1.0';

    $table_name = $wpdb->prefix . 'fcashdata';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE ".$table_name." (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `phash` varchar(32) CHARACTER SET utf8 NOT NULL,
        `code` longtext CHARACTER SET utf8 NOT NULL,
        INDEX (phash),
        PRIMARY KEY  (id)
    ) ".$charset_collate.";";
    
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );

    add_option( 'fcashdata_db_version', $fcashdata_db_version );
}

function fcashdata_plugin_activate() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'fcashdata';
    if($wpdb->get_var("SHOW TABLES LIKE '".$table_name."'") != $table_name) {
        fcashdata_dbinstall();
    }  
}
register_activation_hook( __FILE__, 'fcashdata_plugin_activate' );

register_activation_hookでプラグインが有効化された瞬間にfcashdata_plugin_activate関数が実行されます。
この関数では$wpdb->prefix . ‘fcashdata’というワードプレスのテーブル接頭子とfcashdataをつなげたテーブルが存在しない場合さらにfcashdata_dbinstall関数を実行します。

fcashdata_dbinstall関数ではdbDeltaというワードプレスのテーブル作成に利用されるコア関数で$sql に代入されたテーブル生成のSQL文を実行しています。

テーブルにはid、phash(URLをハッシュ化して入れてキャッシュを呼び出すためのキー値)、code(キャッシュされたページのHTMLを入れます)の三つのセルを作ります。

3 ユーザーがページにアクセスしたときにキャッシュを記録する

次にユーザーがページにアクセスしたときに、キャッシュがデータベースに存在しないときにキャッシュを作ってデータベースに記録するプログラムを作ってまいります。

function fcashcall_is_wplogin(){
    $ABSPATH_MY = str_replace(array('\\','/'), DIRECTORY_SEPARATOR, ABSPATH);
    return ((in_array($ABSPATH_MY.'wp-login.php', get_included_files()) || in_array($ABSPATH_MY.'wp-register.php', get_included_files()) ) || (isset($_GLOBALS['pagenow']) && $GLOBALS['pagenow'] === 'wp-login.php') || $_SERVER['PHP_SELF']== '/wp-login.php');
}

function fcashcall_back($buffer) {
    
    if ( ! is_admin() && ! fcashcall_is_wplogin() && strlen($buffer)>0 && ! is_user_logged_in()) {
        if(is_singular() || is_archive() || is_404() ||  is_front_page() || is_home()){
            $actual_link = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
            $phash = md5($actual_link);
            fcashcall_storecash($phash,$buffer);
        }
    }
    
    return $buffer;
}
function fcashbuf_start() { ob_start("fcashcall_back"); }
function fcashbuf_end() { ob_end_flush(); }
add_action('after_setup_theme', 'fcashbuf_start');
add_action('shutdown', 'fcashbuf_end');

最後の4行はページが表示開始されてから、終わるまでのHTML出力をワードプレス側で取り出してfcashcall_back関数で処理するフックです。

fcashcall_back関数を見ていきましょう。
if ( ! is_admin() && ! fcashcall_is_wplogin() && strlen($buffer)>0 && ! is_user_logged_in()) {
この部分は、ユーザーが表示しているページが、管理画面内のページでなく かつ ログイン画面ではなく(独自関数) かつ HTMLコード(bufferに入っています)が0文字以上 かつ ユーザーがログインしていないとき

さらに

is_singular() || is_archive() || is_404() || is_front_page() || is_home()
ユーザーが表示しているページが、単ページ もしくは アーカイブ もしくは 404ページ もしくはフロントページ もしくは トップページ の場合にキャッシュを保存します。

このキャッシュを保存する機能はfcashcall_storecash関数にまとめます。

4 キャッシュをデータベースに記録する

先ほどのfcashcall_storecash関数は下記のようになります。
この関数ではまず$phashというURLをハッシュ化した値でデータベースにこのページがすでにあるかを調べます。

function fcashcall_storecash($phash,$buffer){
     
    global $wpdb;
    $table_name = $wpdb->prefix . 'fcashdata';
    $row = $wpdb->get_row("SELECT * FROM ".$wpdb->prefix."fcashdata WHERE phash = '".$phash."'");

    if(count($row)==0){
        $results = $wpdb->get_results( "INSERT INTO ".$wpdb->prefix."fcashdata (`id`, `phash`, `code`) VALUES (NULL, '".$phash."', '".base64_encode($buffer)."');" );
    }

}

if(count($row)==0){ にてキャッシュデータが存在しない場合は$phashと、$buffer(ページHTMLコード)をBase64エンコードしたものをデータベースに記録します。

※Base64エンコードは文字列を64種類の印字可能な英数字のみを用いてフォーマットするPHPの関数です。Base64エンコードして保存することによりワードプレスが勝手にHTMLコードの保存時出力時にデータを加工することを防ぎます。

5 キャッシュがある場合ワードプレスがページを出力する前にデータベースから直接高速出力する

ワードプレスのテーマが読み込まれて出力される前に、プラグインが読み込まれてすぐキャッシュがある場合にそちらを高速出力する関数を作ります。

function fcash_loadcash(){
    $logincookie = $_COOKIE['wordpress_logged_in_'.COOKIEHASH];
    if(empty($logincookie) && $_SERVER["REQUEST_METHOD"] != "POST"){
        $actual_link = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        $phash = md5($actual_link);
        global $wpdb;
        $row = $wpdb->get_row("SELECT * FROM ".$wpdb->prefix."fcashdata WHERE phash = '".$phash."'");
        if(! empty($row)){
            echo base64_decode($row->code);
            exit();
        }
        
    }
}
add_action( 'plugins_loaded', 'fcash_loadcash' );

plugins_loadedアクションにフックし、

if(empty($logincookie) && $_SERVER[“REQUEST_METHOD”] != “POST”){
ユーザーがログインしていない、かつページがフォームなどの送信を含まない場合に、

$phash = md5($actual_link);
現在表示中のURLをハッシュ化してデータベースに問い合わせ、

echo base64_decode($row->code);
ある場合はBase64値をもとのHTMLに戻して出力します。

6 ページ更新時などにキャッシュを削除する

ワードプレスでページが管理画面からつくられたり更新したりした場合にキャッシュを削除します。

function fcashdeletecash(){ //キャッシュテーブルをクリアします
    global $wpdb;
    $wpdb->query( "DELETE FROM `".$wpdb->prefix."fcashdata`;" );
    $wpdb->query( "ALTER TABLE ".$wpdb->prefix."fcashdata` auto_increment = 1" );
}
add_action('delete_post', function($post_id){ //投稿が削除されたときにキャッシュを削除します
    fcashdeletecash();
});
add_action('wp_trash_post', function($post_id){ //投稿がごみ箱に入れられたときにキャッシュを削除します
    fcashdeletecash();
});
add_action( 'wp_insert_post', function($post_id, $post, $update){ //投稿が追加されたときにキャッシュを削除します
    fcashdeletecash();
});
add_action( 'save_post', function ( $post_id , $post, $update) { //投稿が保存されたとき(かつレビジョンでない場合)にキャッシュを削除します
    if ( wp_is_post_revision( $post_ID ) )
		return;
    fcashdeletecash( $post_id );
}, 10 );

このコンテンツは役に立ちましたか?

関連コンテンツ

コメントを投稿する


上の計算式の答えを入力してください