Sometimes we may have a reason to use file-based transients instead of a default DB transients.
For example, most cache plugins automatically moves transients into external cache systems such as Redis, Memcached which might be a problem. Because if for some reason redis cache is reset – then all transients get lost – which is very bad for sure.
Transients are not always data which can easily be regenerated – sometimes they contain very important temporary data and should be kept until it expires.
That’s why W3Total Cache plugin has a great feature for it – you can keep a default transient storage(DB) while using Redis or other external object caching software.
For my own codes, sometimes i use filesystem based transient which i built for myself.
Here are set and get functions:
if ( ! defined( 'ABSPATH' ) ) exit;
define('PSEUDO_TRANSIENT_DATA_DIR',wp_get_upload_dir()['basedir']);
function gvn_set_pseudo_transient( $key, $value, $expire_in_seconds = 3600 ) {
if ( defined( 'GVN_USE_REAL_TRANSIENTS' ) ) {
set_transient( $key, $value, $expire_in_seconds );
} else {
global $wp_filesystem;
// Ensure WP_Filesystem is loaded
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
// Force direct method for file handling
add_filter( 'filesystem_method', function() {
return 'direct';
} );
// Initialize WP_Filesystem
if ( ! WP_Filesystem() ) {
return false;
}
$dir = PSEUDO_TRANSIENT_DATA_DIR;
if ( ! $wp_filesystem->is_dir( $dir ) ) {
if ( ! $wp_filesystem->mkdir( $dir ) ) {
return false;
}
}
$file_path = trailingslashit( $dir ) . sanitize_file_name( $key ) . '.json';
$expire_file_path = trailingslashit( $dir ) . sanitize_file_name( $key ) . '_expire.json';
// Save value file
$file_contents = wp_json_encode( $value );
if ( ! $wp_filesystem->put_contents( $file_path, $file_contents, FS_CHMOD_FILE ) ) {
return false;
}
// Save expiration file
$expire_timestamp = time() + $expire_in_seconds;
if ( ! $wp_filesystem->put_contents( $expire_file_path, wp_json_encode( $expire_timestamp ), FS_CHMOD_FILE ) ) {
return false;
}
return true;
}
}
function gvn_get_pseudo_transient( $key ) {
if ( defined( 'GVN_USE_REAL_TRANSIENTS' ) ) {
$value = get_transient( $key );
return $value !== false ? $value : false;
} else {
global $wp_filesystem;
// Initialize WP_Filesystem
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
add_filter( 'filesystem_method', function() {
return 'direct';
} );
if ( ! WP_Filesystem() ) {
return false;
}
$dir = PSEUDO_TRANSIENT_DATA_DIR;
$file_path = trailingslashit( $dir ) . sanitize_file_name( $key ) . '.json';
$expire_file_path = trailingslashit( $dir ) . sanitize_file_name( $key ) . '_expire.json';
// Check expiration file
if ( $wp_filesystem->exists( $expire_file_path ) ) {
$expire_contents = $wp_filesystem->get_contents( $expire_file_path );
$expire_timestamp = json_decode( $expire_contents, true );
if ( time() > $expire_timestamp ) {
return false; // Expired
}
}
// Read value file
if ( $wp_filesystem->exists( $file_path ) ) {
$file_contents = $wp_filesystem->get_contents( $file_path );
return json_decode( $file_contents, true );
}
return false;
}
}
function gvn_delete_old_autogenerate_files() {
$dir = PSEUDO_TRANSIENT_DATA_DIR;
if ( ! is_dir( $dir ) ) {
return false;
}
$files = scandir( $dir );
if ( $files === false ) {
return false;
}
$now = time();
$files_deleted = 0;
foreach ( $files as $file ) {
if ( in_array( $file, [ '.', '..' ], true ) || strpos( $file, '_expire.json' ) === false ) {
continue;
}
$expire_file_path = trailingslashit( $dir ) . $file;
$value_file_path = str_replace( '_expire.json', '.json', $expire_file_path );
if ( is_file( $expire_file_path ) ) {
$expire_contents = file_get_contents( $expire_file_path );
$expire_timestamp = json_decode( $expire_contents, true );
// Delete files if expired
if ( $expire_timestamp < $now ) {
if ( wp_delete_file( $expire_file_path ) && wp_delete_file( $value_file_path ) ) {
$files_deleted++;
}
}
}
}
return $files_deleted;
}
// Schedule directory cleanup daily
add_action( 'wp_scheduled_delete', 'gvn_delete_old_autogenerate_files' );
So here is how it works:
gvn_set_pseudo_transient – instead of set_transient
gvn_get_pseudo_transient – instead of get_transient
gvn_delete_old_autogenerate_files – is scheduled to clear expired transient files from the directory.
The code will automatically work by just putting it as a snippet to functions.php or Snippets plugin.
The only check should be made is making sure wp-content/uploads is writable (which usually is)
Discover more from WP DEV - Elvin Haci
Subscribe to get the latest posts sent to your email.