Membuat Plugin Cache untuk WordPress

6 min read

Membuat Plugin Cache untuk WordPress
Membuat Plugin Cache untuk WordPress (Hak cipta logo: Automattic)

TeknoCerdas.com – Salam cerdas untuk kita semua. WordPress adalah Content Management System (CMS) paling populer saat ini. Terlepas dari codebase yang menurut sebagian orang “tidak rapi” namun semua itu bisa ditutupi dengan dokumentasi, templating dan sistem hooks yang super lengkap. Tulisan ini adalah sebuah tutorial bagaimana membuat WordPress cache plugin sendiri. Ya, anda bisa membuatnya dan caranya cukup mudah.

Sebagai pengguna WordPress kita pasti familiar dengan plugin WP Super Cache, W3 Total Cache, WP Rocket dan semacamnya. Kesemua itu adalah beberapa dari sekian banyak WordPress plugin yang diperuntukkan untuk cache.

Apa maksud dari cache? Cache adalah proses untuk membuat salinan statis sebagian atau seluruh bagian dari sebuah halaman WordPress yang dibuka. Sehingga ketika halaman tersebut diakses untuk kedua kali dan seterusnya tidak perlu ada query database, pemanggilan fungsi dan sebagainya. Hasilnya adalah waktu load website menjadi jauh lebih cepat.

Baca Juga
Membuat Plugin WordPress: Penghitung Kata

Daftar isi.

Konsep Cache pada WordPress

Pada WordPress dikenal sebuah file bernama wp-content/advanced-cache.php. File ini adalah file special dan hanya akan diproses ketika konstanta WP_CACHE diset ke true pada file wp-config.php.

Logika pemrosesan dari plugin yang akan dibuat harus dipasang atau diload pada file wp-content/advanced-cache.php. Kode yang ada pada file ini adalah salah satu yang paling awal dijalankan WordPress sehingga belum ada proses-proses “berat” dilakukan. Sehingga ini adalah tempat yang cocok untuk meletakkan kode cache.

Satu lagi fungsi yang tidak kalah penting adalah ob_start(). Ini adalah fungsi bawaan dari PHP untuk mengaktifkan output buffering. Output buffer adalah segala hal yang akan dikirimkan oleh WordPress kepada browser atau client. Dengan memanipulasi output buffer maka kita bisa menyimpan output lengkap halaman WordPress untuk disimpan sebagai file statis.

Baca Juga
Static WordPress Hosting pada Infrastruktur TeknoCerdas

Struktur dari Plugin

Plugin yang akan dibuat bernama TeknoCerdas Cache. Struktur dari plugin ini adalah sebagai berikut.

File/DirektoriKegunaan
teknocerdas-cache/Direktori plugin
- cache-prosessor.phpFile untuk memproses cache
- options-page.phpHalaman Purge Cache pada admin
- teknocerdas-cache.phpFile utama plugin untuk menghubungkan dengan WordPress hooks
- uninstall.phpPenghapusan file-file yang tidak diperlukan
wp-content/cache/teknocerdas-cache/Direktori untuk menyimpan file-file cache
Struktur file dari plugin TeknoCerdas Cache

Membuat Kode dari Plugin TeknoCerdas Cache

Buat sebuah direktori baru pada wp-content/plugins/ dengan nama teknocerdas-cache. Gunakan perintah berikut jika menggunakan CLI.

$ mkdir wp-content/plugins/teknocerdas-cache

Saat ini direktori tersebut masih kosong. Berikutnya kita akan membuat file-file PHP yang diperlukan agar plugin tersebut dapat berjalan.

Membuat file teknocerdas-cache.php

Ini adalah file utama dari plugin. Konvensi dari WordPress adalah nama file utama dari plugin sama dengan nama direktorinya. Buka teks editor dan mulai buat file wp-content/plugins/teknocerdas-cache/teknocerdas-cache.php.

Berikut ini adalah konten dari file tersebut.

<?php
/**
 * Plugin Name: TeknoCerdas Cache
 * Plugin URI: https://teknocerdas.com/programming/tutorial-wordpress-membuat-plugin-cache/
 * Description: A dead simple cache plugin demo.
 * Author: Rio Astamal
 * Version: 1.0.0
 * Text Domain: simple-cache
 * Author URI: https://rioastamal.net
 */

defined( 'ABSPATH' ) || exit('Access denied.');

if (is_admin()) {
    add_action( 'admin_init', function() {
        register_setting('teknocerdas-cache-group', 'enable-cache');
    });

    add_action('admin_menu', function() {
        $teknocerdasCachePage = function() {
            require __DIR__ . '/options-page.php';
        };

        add_options_page(
            __( 'TeknoCerdas Cache - Options', 'textdomain' ),
            __( 'TeknoCerdas Cache', 'textdomain' ),
            'manage_options',
            'teknocerdas-cache',
            $teknocerdasCachePage
        );
    });

    function teknocerdas_caches_delete() {
        $cacheDir = WP_CONTENT_DIR . '/cache/teknocerdas-cache';
        $cacheFiles = glob($cacheDir . '/*');

        foreach ($cacheFiles as $_file) {
            // No fancy validation and assume everything is works fine
            if (! is_file($_file)) { continue; }
            unlink($_file);
        }
    }

    register_activation_hook(__FILE__, function() {
        // Write advanced-cache.php file
        $generatedAt = gmdate('c');
        $cacheProsessor = __DIR__ . '/cache-processor.php';
        $fileContent = <<<EOF
<?php
/**
 * This file are generated automatically by teknocerdas-cache plugin at {$generatedAt}.
 */
defined('ABSPATH') || exit('Access denied.');

// This is the key to do caching!
require '$cacheProsessor';
EOF;

        file_put_contents(WP_CONTENT_DIR . '/advanced-cache.php', $fileContent);
    });

    register_deactivation_hook(__FILE__, function() {
        $generatedAt = gmdate('c');
        file_put_contents(WP_CONTENT_DIR . '/advanced-cache.php', <<<EOF
<?php
/**
 * This file are generated automatically by teknocerdas-cache plugin at {$generatedAt}.
 * Plugin status is disabled. So nothing to do here.
 */
EOF);
    });
}

WordPress mengambil informasi plugin dari komentar atau docblock /*..*/ yang ada pada awal file diatas.

Ada beberapa hal yang dilakukan disini yaitu:

  • Membuat submenu baru pada Admin didalam menu Settings. Lihat add_action('admin_menu')
  • Membuat file wp-content/advanced-cache.php saat plugin diaktifkan agar meload file cache-processor.php.
  • Menulis file wp-content/advanced-cache.php saat plugin dinonaktifkan agar tidak meload file cache-prosessor.php.
  • Fungsi teknocerdas_caches_delete() digunakan untuk menghapus file hasil cache yang akan dipanggil pada halaman options.

Membuat file options-page.php

File ini fungsinya adalah menampilkan halaman options yang didalamnya terdapat tombol untuk membersihkan file cache yang ada pada direktori wp-content/cache/teknocerdas-cache/.

Berikut ini adalah konten dari file options-page.php.

<?php
defined( 'ABSPATH' ) || exit('Access denied.');

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    check_admin_referer( 'teknocerdas-cache-update' );

    teknocerdas_caches_delete();

    echo <<<HTML
    <div class="notice notice-success is-dismissible">
        <p>All cache files has been deleted.</p>
    </div>
HTML;
}

?><div class="wrap">
<h1>TeknoCerdas Cache Options</h1>
<form method="post" action=""><?php
    wp_nonce_field('teknocerdas-cache-update');
?><p>To delete all files in cache folder press the <strong>Purge Caches</strong> button.</p><?php
    submit_button('Purge Caches', $__type = 'primary', $__name = 'btn-delete-cache');
?></form>
</div>

File ini sangat sederhana. Yaitu ketika tombol Purge Caches ditekan maka otomatis form disubmit. Setelah itu fungsi teknocerdas_caches_delete() akan dipanggil. Fungsi ini telah didefinisikan sebelumnya di file utama.

Membuat file cache-prosessor.php

File ini berfungsi untuk menulis cache ke file dan juga membaca cache tersebut jika memang request yang diminta sudah berada pada cache. Ketika sebuah halaman dibuka pertama kali maka cache akan dibuat. Cache dibuat berdasarkan md5 checksum dari Request URI. Yaitu dari variabel PHP $_SERVER['REQUEST_URI']. md5 checksum ini juga dijadikan sebagai nama file untuk disimpan pada wp-content/cache/teknocerdas-cache/.

Berikut adalah konten dari file tersebut.

<?php
defined( 'ABSPATH' ) || exit('Access denied.');

// Do not cache admin page
if (is_admin()) { return; }

// Do not cache not GET request
if ($_SERVER['REQUEST_METHOD'] !== 'GET') { return; }

// Do not cache JSON request
if (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false) {
    return;
}

// When PHP send output buffer to browser it will catched by this function.
// We then modify the buffer to create our cache file.
ob_start(function($buffer) {
    $cacheDir = WP_CONTENT_DIR . '/cache/teknocerdas-cache';
    $cacheKey = md5($_SERVER['REQUEST_URI']);
    $cacheFile = $cacheDir . '/' . $cacheKey;
    $cacheMaxAge = 1 * 3600 * 24; // 1 day

    if (file_exists($cacheFile)) {
        $now = time();
        $lastFileModificationTime = filemtime($cacheFile);

        // If cache file is more than 1 day old then skip and request new one
        if ($lastFileModificationTime + $cacheMaxAge > $now) {
            header('Cache-Control: max-age=' . $cacheMaxAge);
            header('X-TeknoCerdas-Cache-Hit: yes');
            return file_get_contents($cacheFile);
        }
    }

    if (! file_exists($cacheDir)) {
        mkdir($cacheDir, $__mode=0755, $__recursive=true);
    }

    $date = gmdate('c');
    $signature = "\n<!-- Generated by TeknoCerdas Cache at $date -->";
    file_put_contents($cacheFile, $buffer . $signature);
    header('X-TeknoCerdas-Cache-Hit: miss');

    return false;
});

Tugas utama dari file ini adalah melakukan penghadangan atau intercept terhadap output yang akan dikirimkan WordPress. Untuk itu digunakan fungsi ob_start(). Fungsi ini menerima Callback dimana kita dapat mengakses dan memodifikasi output buffer sesuai keinginan.

Secara default umur dari cache adalah 1 hari. Ketika sebuah halaman pertama kali dibuka maka belum ada cache. Jika demikian maka

  1. Modifikasi buffer dengan menambahkan signature pada akhir halaman
  2. Buat cache file dengan md5sum dari request uri
  3. Tambahkan HTTP header agar browser melakukan cache juga selama 1 hari pada local disk. Lihat Cache-Control: max-age=DETIK
  4. Tambahkan HTTP header yang mengindikasikan halaman tersebut diambil dari cache atau tidak lewat header X-TeknoCerdas-Cache-Hit. “Miss” berarti tidak melewati cache dan “Hit” berarti dari cache.
  5. Cache hanya dilakukan pada halaman depan bukan admin page dan tidak berlaku untuk request JSON dan XML.

Membuat file uninstall.php

File ini digunakan untuk melakukan pembersihan file-file yang sudah tidak digunakan oleh plugin TeknoCerdas Cache seperti file hasil cache dan file advanced-cache.php.

<?php

// if uninstall.php is not called by WordPress, die
if (!defined('WP_UNINSTALL_PLUGIN')) {
    die('Access denied.');
}

$cacheDir = WP_CONTENT_DIR . '/cache/teknocerdas-cache';

foreach (glob($cacheDir . '/*') as $_file) {
    if (! is_file($_file)) { continue; }
    unlink($_file);
}

rmdir($cacheDir);
@unlink(WP_CONTENT_DIR . '/advanced-cache.php');

WordPress secara otomatis akan mengeksekusi file ini sesaat setelah proses uninstall berjalan.

Mencoba Plugin TeknoCerdas Cache

Saatnya untuk melakukan percobaan terhadap plugin “TeknoCerda Cache” yang baru saja dibuat. Masuk ke WordPress administrator page kemudian ke menu Plugins.

Seharusnya, jika kode benar maka akan muncul sebuah plugin baru bernama “TeknoCerdas Cache” yang belum diaktifkan.

Aktivasi Plugin TeknoCerdas Cache
Melakukan aktivasi plugin TeknoCerdas Cache

Lakukan aktivasi TeknoCerdas Cache plugin agar plugin dapat mulai memproses request halaman.

Setelah plugin aktif perlu sedikit perubahan konfigurasi pada file wp-config.php. Yaitu menambahkan konstanta WP_CACHE. Tambahkan baris berikut pada file wp-config.php.

define('WP_CACHE', true); // Activate advance caching

Untuk memastikan plugin benar-benar telah berjalan sesuai ekspektasi lakukan request ke salah satu halaman, misal halaman depan atau homepage. Sebagai contoh URL WordPress yang digunakan adalah http://localhost:8000/.

Buka halaman WordPress anda pada browser atau menggunakan command line HTTP client seperti cURL.

$ curl -q -D /dev/stdout http://localhost:8000 | less
HTTP/1.1 200 OK
Date: Sun, 10 Jan 2021 12:09:28 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/7.4.12
Link: <http://localhost:8000/index.php?rest_route=/>; rel="https://api.w.org/"
X-TeknoCerdas-Cache-Hit: miss
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
...[CUT]...
        </body>
</html>

Dapat terlihat jika terdapat header X-TeknoCerdas-Cache-Hit dengan nilai “miss” artinya belum ada cache pada request tersebut. Namun sekarang coba lihat pada direktori file cache harusnya terdapat sebuah file cache.

$ ls -lh wordpress/wp-content/cache/teknocerdas-cache/
total 56
-rw-r--r--  1 rioastamal  staff    25K Jan 10 19:09 6666cd76f96956469e7be39d750cc7d9

Dapat terlihat terdapat sebuah file cache. Itu adalah file cache untuk request halaman homepage http://localhost:8000/. Coba ulangi request sebelumnya dengan melakukan reload browser atau request ulang dengan cURL.

$ curl -q -D /dev/stdout http://localhost:8000
Date: Sun, 10 Jan 2021 12:19:35 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/7.4.12
Link: <http://localhost:8000/index.php?rest_route=/>; rel="https://api.w.org/"
Cache-Control: max-age=86400
X-TeknoCerdas-Cache-Hit: yes
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
[...CUT...]
        </body>
</html>

<!-- Generated by TeknoCerdas Cache at 2021-01-10T12:09:28+00:00 -->

Dapat terlihat jika sekarang terdapat header X-TeknoCerdas-Cache-Hit bernilai yes. Artinya request tersebut diambil dari file cache. Hal itu juga terkonfirmasi dengan konten HTML yang terdapat signature:

<!-- Generated by TeknoCerdas Cache at 2021-01-10T12:09:28+00:00 -->

Untuk optimasi cache TeknoCerdas Cache juga mengirimkan header Cache-Control: max-age=86400 yang artinya browser harusnya melakukan cache lokal selama 1 hari. Selama user tidak melakukan hard-reload harusnya ketika mengunjungi halaman http://localhost:8000/ selama 1 hari kedepan cache akan diambil dari lokal disk komputer client.

Jika ingin melakukan penghapusan file cache dapat dilakukan secara manual dengan masuk ke menu Settings kemudian TeknoCerdas Cache. Tersedia tombol Purge Caches untuk menghapus semua file cache yang ada.

TeknoCerdas Plugin Purge Caches
Penghapusan cache pada TeknoCerdas Cache

Improvisasi Plugin

Kita telah membuat plugin sederhana untuk melakukan cache request pada WordPress. Plugin ini secara fitur masih sederhana. Berikut ini adalah fitur-fitur yang dapat ditambahkan pada plugin ini.

  • Melakukan kompresi file cache dengan gzip.
  • Menambahkan storage cache driver misal Redis atau Memcache.
  • Menambahkan opsi untuk melakukan konfigurasi cache driver, kompresi dan lama cache disimpan.
  • Melakukan penulisan konstanta WP_CACHE secara otomatis pada wp-config.php.
  • Menambahkan opsi halaman yang harus dicache atau tidak.
  • Mengubah logika penulisan file cache untuk integrasi dengan web server sehingga tidak perlu ada pemanggilan WordPress atau PHP sama sekali.

Selamat mencoba untuk melakuakn improvisasi plugin cache.