Built-in Rules

MilliCache includes default rules that handle common caching scenarios. All built-in rules have negative or zero priority, so your custom rules (->order({10+})) run after them and can override their decisions.

Bootstrap Phase Rules#Copied!

Execute before WordPress loads via advanced-cache.php.

Core Bypass Rules (Order -10)#Copied!

These run first and bypass caching for non-cacheable scenarios:

Rule ID Condition Result
millicache:const:wp-cache WP_CACHE !== true Bypass
millicache:request:check-method Method not GET/HEAD Bypass
millicache:request:cli Running in WP-CLI Bypass
millicache:request:xmlrpc XMLRPC_REQUEST is true Bypass
millicache:request:file URL ends with file extension Bypass
millicache:request:rest URL contains wp-json Bypass
millicache:config:ttl-not-set TTL is 0 or negative Bypass

Configuration-Based Rules (Order 0)#Copied!

Apply settings from your configuration:

Rule ID Condition Result
millicache:config:nocache-cookies Excluded cookie present Bypass
millicache:config:nocache-paths URL matches excluded path Bypass

Default excluded cookies:

  • wp-*pass* — WordPress password-protected content
  • comment_author_* — Comment author cookies

WordPress Phase Rules#Copied!

Execute after WordPress loads on the template_redirect hook.

Context-Based Rules (Hook Priority 20)#Copied!

Rule ID Condition Result
millicache:wp:logged-in User is logged in Bypass
millicache:wp:response:code HTTP status ≠ 200 Bypass
millicache:wp:const:donotcachepage DONOTCACHEPAGE defined Bypass
millicache:wp:const:doing-cron DOING_CRON defined Bypass
millicache:wp:const:doing-ajax DOING_AJAX defined Bypass

Rule Priority System#Copied!

Rules execute in priority order (lower numbers first):

Priority Who Uses It Purpose
-10 Core bypass rules Fundamental checks (methods, CLI, etc.)
0 Configuration rules Apply user settings
10+ Your custom rules Override or extend defaults

All Rules Run#Copied!

MilliRules evaluates all rules in order — there's no short-circuit behavior. Later rules can override earlier rules' decisions.

 1// Built-in rule (order -10) sets do_cache(false) for POST requests
 2// Your rule (order 10) runs AFTER and can override it
 3Rules::create( 'mysite:cache-post-search', 'php' )
 4    ->order( 10 )
 5    ->when()
 6        ->request_method( 'POST' )
 7        ->request_url( '/search/*' )
 8    ->then()
 9        ->do_cache( true )  // Overrides the earlier bypass
10    ->register();

This means:

  • All your rules always run after built-in rules
  • Your rules can override built-in decisions (the last do_cache() wins)
  • To completely replace a built-in rule, use the same rule ID (see below)

Available Actions#Copied!

Bootstrap Phase Actions#Copied!

Available in php rules (before WordPress):

Action Description Example
do_cache( $bool, $reason ) Enable/disable caching ->do_cache( false, 'Preview' )
set_ttl( $seconds ) Override TTL ->set_ttl( 3600 )
set_grace( $seconds ) Override grace period ->set_grace( 86400 )

WordPress Phase Actions#Copied!

Available in wp rules (after WordPress loads):

Action Description Example
do_cache( $bool, $reason ) Enable/disable caching ->do_cache( false, 'Admin' )
set_ttl( $seconds ) Override TTL ->set_ttl( 300 )
set_grace( $seconds ) Override grace period ->set_grace( 3600 )
add_flag( $flag ) Add cache flag ->add_flag( 'custom:flag' )
remove_flag( $flag ) Remove cache flag ->remove_flag( 'home' )
clear_cache( $targets ) Clear cache entries ->clear_cache( ['post:*'] )
clear_site_cache() Clear entire site ->clear_site_cache()

Available Conditions#Copied!

Core Conditions#Copied!

Available in both php (bootstrap) and wp (WordPress) phases:

Condition Description Example
constant( $name, $value ) Check constant value ->constant( 'WP_DEBUG', true )
custom( $id, $callback ) Custom callback ->custom( 'my-check', fn() => ... )
request_method( $methods ) HTTP method ->request_method( 'POST' )
request_url( $pattern ) URL pattern match ->request_url( '/shop/*' )
cookie( $name, $value ) Cookie check ->cookie( 'currency', 'EUR' )

WordPress is_* Conditions#Copied!

All is_* methods are available in wp phase rules (require WordPress context):

Condition Description
is_singular( $post_types ) Single post/page/CPT
is_front_page() Front page
is_home() Blog homepage
is_post_type_archive( $types ) Post type archive
is_category( $category ) Category archive
is_tag( $tag ) Tag archive
is_tax( $taxonomy, $term ) Taxonomy archive
is_author( $author ) Author archive
is_date() Date archive
is_feed( $feeds ) Feed page
is_user_logged_in() User logged in

WordPress has_* Conditions#Copied!

All has_* methods are available in wp phase rules (require WordPress context):

Condition Description
has_term( $term, $taxonomy ) Post has specific term
has_block( $block_name ) Post contains block
has_tag( $tag ) Post has tag
has_category( $category ) Post has category
has_post_thumbnail() Post has featured image
has_excerpt() Post has excerpt
has_post_format( $format ) Post has format
has_nav_menu( $location ) Menu location has menu
has_custom_logo() Site has custom logo

Debugging Rules#Copied!

Enable Debug Mode#Copied!

 1define( 'MC_CACHE_DEBUG', true );

Check Response Headers#Copied!

The X-MilliCache-Status header shows the caching result:

Value Meaning
hit Served from cache
miss Not cached, will be stored
bypass A rule prevented caching
grace Serving stale while regenerating

List Registered Rules#Copied!

 1use MilliCacheDepsMilliRulesRules;
 2
 3// Log all rules
 4foreach ( Rules::all() as $rule ) {
 5    error_log( sprintf(
 6        'Rule: %s (order: %d, phase: %s)',
 7        $rule['id'],
 8        $rule['order'],
 9        $rule['phase']
10    ) );
11}

Override / Unregister Built-in Rules#Copied!

To change the behavior of a built-in rule, you can unregister them or create your own with the same ID:

 1add_action('template_redirect', function() {
 2    // Unregister a built-in rule to completely remove its behavior
 3    Rules::unregister( 'millicache:wp:const:doing-ajax' );
 4});
 5
 6// Override the logged-in user bypass to allow caching for subscribers
 7Rules::create( 'millicache:wp:logged-in' )  // Same ID as built-in
 8    ->on( 'template_redirect', 20 )         // Same hook & priority as built-in
 9    ->order( 10 )                           // Higher order to run after built-in
10    ->when()
11        ->is_user_logged_in()
12        ->custom( 'is-editor-or-higher', function() {
13            return current_user_can( 'edit_posts' );
14        })
15    ->then()
16        ->do_cache( false, 'Editor role or above' )
17    ->register();

Now subscribers can see cached pages, but editors and admins still bypass.

Next Steps#Copied!