Skip to content

Instantly share code, notes, and snippets.

@wpeasy
Created April 2, 2025 02:10
Show Gist options
  • Save wpeasy/b212cebf44f56c5ee02530d8139328d9 to your computer and use it in GitHub Desktop.
Save wpeasy/b212cebf44f56c5ee02530d8139328d9 to your computer and use it in GitHub Desktop.
WP Custom REST Endpoint Cache with Transients.
<?php
class WPE_Simple_REST_Cache {
const CACHE_TTL_DEFAULT = 300; // 5 minutes
const CACHE_PREFIX = 'wpe_rest_cache_';
/**
* Initialise cache hooks.
*/
public static function init() {
add_action('init', [__CLASS__, 'register_cache_clear_hooks']);
add_action('init', [__CLASS__, 'maybe_handle_manual_clear'], 99);
}
/**
* Generate a unique cache key from a REST request.
*
* @param WP_REST_Request $request The REST request object.
* @return string Cache key.
*/
public static function get_cache_key($request) {
$method = $request->get_method();
$route = $request->get_route();
$params = $request->get_params();
$base = strtoupper($method) . '|' . $route . '|' . json_encode($params);
return self::CACHE_PREFIX . md5($base);
}
/**
* Get cached data for a request.
*
* @param WP_REST_Request $request
* @return mixed|false
*/
public static function get($request) {
return get_transient(self::get_cache_key($request));
}
/**
* Set cached data for a request.
*
* @param WP_REST_Request $request
* @param mixed $data
* @param int $TTL Optional. Cache duration in seconds.
* @return bool
*/
public static function set($request, $data, $TTL = self::CACHE_TTL_DEFAULT) {
return set_transient(self::get_cache_key($request), $data, $TTL);
}
/**
* Delete cache for a specific request.
*
* @param WP_REST_Request $request
* @return bool
*/
public static function delete($request) {
return delete_transient(self::get_cache_key($request));
}
/**
* Delete all cache entries created by this class.
*/
public static function delete_all() {
global $wpdb;
$prefix = is_multisite() ? '_site_transient_' : '_transient_';
$like_main = $wpdb->esc_like($prefix . self::CACHE_PREFIX) . '%';
$like_timeout = $wpdb->esc_like($prefix . 'timeout_' . self::CACHE_PREFIX) . '%';
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options}
WHERE option_name LIKE %s OR option_name LIKE %s",
$like_main,
$like_timeout
)
);
}
/**
* Register hooks for clearing cache when popular caching plugins flush their caches.
*/
public static function register_cache_clear_hooks() {
// Core hook for manual/custom use
add_action('wpe_rest_cache_clear', [__CLASS__, 'delete_all']);
// WP Rocket
add_action('rocket_clear_cache', [__CLASS__, 'delete_all']);
add_action('rocket_rucss_purge_complete', [__CLASS__, 'delete_all']);
// W3 Total Cache
add_action('w3tc_flush_all', [__CLASS__, 'delete_all']);
// LiteSpeed Cache
add_action('litespeed_purge_all', [__CLASS__, 'delete_all']);
// FlyingPress
add_action('flying_press_clear_cache_all', [__CLASS__, 'delete_all']);
// WP Super Cache
add_action('wp_cache_cleared', [__CLASS__, 'delete_all']);
// Cache Enabler (KeyCDN)
add_action('ce_action_clear_cache', [__CLASS__, 'delete_all']);
// Autoptimize
add_action('autoptimize_action_cachepurged', [__CLASS__, 'delete_all']);
// Swift Performance
add_action('swift_performance_clear_cache', [__CLASS__, 'delete_all']);
// Hummingbird
add_action('wphb_clear_cache', [__CLASS__, 'delete_all']);
// Breeze (by Cloudways)
add_action('breeze_clear_cache', [__CLASS__, 'delete_all']);
// SG Optimizer (SiteGround)
add_action('sg_cachepress_purge_cache', [__CLASS__, 'delete_all']);
// NitroPack (less consistent, but safe to include)
add_action('nitropack_clear_cache_all', [__CLASS__, 'delete_all']);
}
/**
* Detect URL param and trigger full cache clear.
*/
public static function maybe_handle_manual_clear() {
if (isset($_GET['wpe_clear_rest_cache'])) {
self::delete_all();
}
}
}
add_action('init', ['WPE_Simple_REST_Cache', 'init']);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment