Last active
October 14, 2025 11:06
-
-
Save kasparsd/0bf0c8aad5bb1dbefb1a67836f819dcf to your computer and use it in GitHub Desktop.
Autoload all WordPress transients including those with expiration (add this as a mu-plugin)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: Transient Autoload | |
| * Description: Autoload transients with expiration since they're not preloaded by WP core. | |
| * Version: 1.0.0 | |
| */ | |
| namespace Transient_Autoload; | |
| function get_transient_option(): array { | |
| global $wpdb; | |
| $transient_options = $wpdb->get_results( | |
| "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_transient_%'", | |
| ARRAY_A | |
| ); | |
| if ( ! empty( $transient_options ) && is_array( $transient_options ) ) { | |
| return array_combine( | |
| array_column( $transient_options, 'option_name' ), | |
| array_column( $transient_options, 'option_value' ) | |
| ); | |
| } | |
| return []; | |
| } | |
| if ( function_exists( 'wp_cache_set_multiple' ) && ! wp_installing() && ! wp_using_ext_object_cache() ) { | |
| $transient_options = get_transient_option(); | |
| // Populate run-time object cache with expiring transients which are not autoloaded. | |
| wp_cache_set_multiple( $transient_options, 'options' ); | |
| /** | |
| * Avoid DB lookups for known non-existent transients. | |
| * | |
| * Use the `all` hook since get_transient() doesn't have anything firing | |
| * before wp_prime_option_caches() which does the DB lookup. | |
| * | |
| * @see https://github.com/WordPress/wordpress-develop/blob/97382397b2bd7c85aef6d4cd1c10bafd397957fc/src/wp-includes/option.php#L1465-L1466 | |
| */ | |
| add_action( | |
| 'all', | |
| function( string $filter_name ) use ( $transient_options ) { | |
| if ( 0 === strpos( $filter_name, 'pre_transient_' ) ) { | |
| $transient_option_name = substr( $filter_name, 3 ); // Remove the `pre` prefix. | |
| $notoptions = wp_cache_get( 'notoptions', 'options' ); | |
| if ( is_array( $notoptions ) && ! isset( $notoptions[ $transient_option_name ] ) && ! isset( $transient_options[ $transient_option_name ] ) ) { | |
| // Mark transient and timeout options as known notoption. | |
| $notoptions[ $transient_option_name ] = true; | |
| $notoptions[ str_replace( '_transient_', '_transient_timeout_', $transient_option_name ) ] = true; | |
| wp_cache_set( 'notoptions', $notoptions, 'options' ); | |
| } | |
| } | |
| } | |
| ); | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
By default, transient values with expiry aren't included in the
alloptionscache (because they haveautoload=no) so WordPress doesn't preload their values.This must-use plugin adds all transient option values to in-memory cache when an external (persistent) object cache is not used. In case of external object cache, the transient values with expiry timestamp would be cached so no need to re-populate that data.
Use the following snippet to check the DB query with and without the plugin active: