Download the PHP package generoi/sage-cachetags without Composer

On this page you can find all versions of the php package generoi/sage-cachetags. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package sage-cachetags

sage-cachetags

A sage package for tracking what data rendered pages rely on using Cache Tags (inspired by Drupal's Cache Tags).

Example

Front page displays the page content as well as 3 recipe previews. The cache tags might be:

This set of tags will be gathered while rendering the page and then stored in the database and optionally added as a HTTP header.

When any of the posts or terms are updated, page caches and reverse proxies know that the front page cache should be cleared.

Installation

Composer

Plugin

Download the zip, install like a regular plugin, then follow the standalone installation instructions below.

With Acorn (Sage theme)

Start by publishing the config/cachetags.php configuration file using Acorn:

Edit it to your liking and if you're using the database store, scaffold the required database table:

Standalone (without Acorn)

For WordPress sites without Acorn, use the Bootstrap class in your theme's functions.php or a mu-plugin. The Bootstrap class provides a fluent interface for configuration:

If you're using the database store, scaffold the required database table using WP-CLI:

Schema changes are migrated automatically on the next admin request after an update (the table version is tracked in the cachetags_db_version option). On headless or multisite setups, run wp cachetags database to apply migrations across all sites.

Invalidators

Currently it supports Kinsta Page Cache, WP Super Cache, SiteGround Optimizer, WP Rocket and Fastly. You can use multiple invalidators if you eg use Fastly in front of Kinsta and want to invalidate both.

Coarse tags and bulk purges. A coarse tag like archive:post can resolve to many stored URLs (every page that lists posts), which URL-based invalidators must handle without firing thousands of individual purges, since those providers effectively rate-limit purges. They differ in how:

Fastly is unaffected — it purges by Surrogate-Key, so URL count is irrelevant, which makes it the best fit for high-frequency editorial sites.

Stored URL and query strings

Front-end pages are stored under the actual requested URL (including its query string), so a URL-based purge matches the variant a page cache keyed on. A default set of tracking/volatile params (utm_*, gclid/fbclid/dclid/…, _wpnonce, _) is stripped and the rest sorted; keys longer than the varchar(191) column fall back to the path.

On a query-bypass edge — Fastly (purges by Surrogate-Key, ignores the URL) or Kinsta (query-string URLs bypass the cache entirely) — those query-string rows are never cached and so never need purging; they just accumulate in the store (one row per visited ?… combination, including bot/scanner params). A query-bypass site with heavy parameterised traffic can keep the store lean by storing the path only:

To match a URL-keyed edge that does cache query strings (SiteGround, or Kinsta configured to cache GET params) the strip list must equal that edge's — and that's site-specific (our own Fastly VCLs strip anywhere from 5 to 16 params), so align it per site:

Comprehensive query-param normalization is better done at the edge (CDN/VCL) than replicated here.

SiteGround Optimizer

Integration exists if you add the SiteGroundCacheInvalidator invalidator in the config/cachetags.php file.

When more than 50 URLs need purging, the invalidator performs a full cache flush instead of purging each URL individually. This avoids overwhelming SiteGround's cache API with thousands of synchronous requests. The threshold is configurable:

Super Cache

Integration exists if you add the SuperCacheInvalidator invalidator in the config/cachetags.php file.

Kinsta

Two invalidators, differing in how Kinsta resolves the purge:

Add one of them to the invalidator list in config/cachetags.php. The site root (/) is always purged exactly, so a group purge never flushes the whole site.

Cloudflare

Cloudflare Pro plan supports HTTP header purging but an invalidor doesn't exist at the moment. If you're up for it, take a look at the Fastly one as an example.

Fastly

There's both a FastlySoftCacheInvalidator and a FastlyCacheInvalidator (hard) cache invalidator for Fastly (Varnish) proxy cache. Using this set up you do not need a persistent store since Fastly works with HTTP headers. Example config/cachetags.php

`

REST API integration

For headless/decoupled setups where pages are served from the WordPress REST API, enable the RestApi action to tag REST read responses so a frontend or CDN can purge them by cache tag:

Keep Core enabled alongside it: block-derived tags from content.rendered are still collected through Core's render_block hook during the REST request.

What gets tagged:

Only responses that may be publicly cached are tagged: requests are skipped when they are authenticated, use context=edit, carry a password, or are not GET/HEAD. The edge must strip the Cache-Tag header before it reaches clients.

Each response is stored under its canonical URL with sort-normalized query parameters, so variants that produce a different response — pagination/filters (?page=2, ?categories=5), context, and the server params that shape the body (_embed, _fields, _envelope, _locale) — get distinct, CDN-matching store keys and are purged separately. Parameters the route doesn't register (and aren't response-shaping) are dropped so arbitrary client params can't fork the key. Only the random per-request params _wpnonce and _ are stripped unconditionally — any cache entry keyed on them is never reused, so collapsing them can't cause staleness.

Custom routes

The RestApi action only knows about core wp/v2 objects. A custom public route that serves its own cacheable response (sets its own Cache-Control: public, s-maxage=…, e.g. my-plugin/v1/people) is cached at the edge but never purged unless it declares the cache tags its data depends on.

Do it the same way the front end does — add the tags while building the response, from the CacheTags instance (app(CacheTags::class) with Acorn, or CacheTags::getInstance() standalone). With RestApi/HttpHeader enabled they're emitted and stored on rest_post_dispatch:

If the endpoint manages its own Cache-Control and you want full control, set the header yourself (and save() the URL for url-based purge):

Purge them from a small custom Action that hooks the relevant transition_post_status / meta / term events and calls $cacheTags->clear([...]), mirroring Core. (For a third-party route you can't edit, the cachetags/rest-tags filter below is the fallback.)

Filters

Header size limits

Cache providers cap the tag header — Fastly's Surrogate-Key allows 1024 bytes per key and 16384 bytes total, and silently drops the offending key and every key after it once a limit is reached, which would leave content stale. To stay safe (for both front-end pages and REST responses):

(The single-tag length cap — 191, the varchar(191) store column — and the header-token validation pattern are fixed, not filterable: they're tied to the schema and to header safety.)

Front-end tagging

With the Core action enabled, rendered pages are tagged automatically from the template (single/page, taxonomy, author, post-type/date/search archives, attachments) and from core blocks (queries, terms, authors, comments, calendar/archives, site title/tagline/logo, etc.). Classic-theme wp_nav_menu() output is tagged with its menu:{id} so menu edits purge the pages showing it.

Site-identity blocks (core/site-title, core/site-tagline, core/site-logo) are tagged with an option:{name} tag and purged when that option changes. Adjust which options are tracked with the cachetags/options filter:

Options not bound to a specific block are usually better handled with a full cache flush than by tagging every page that might render them.

Zero-config auto-tagging

For themes that render content through custom WP_Query loops (related posts, curated lists) rather than the blocks Core understands, enable the opt-in AutoTag action to tag every queried post and fetched term automatically:

It hooks posts_pre_query (tagging each returned post, plus an archive:{type} for collection queries) and get_the_terms (tagging each term). posts_pre_query is used rather than the_posts because get_posts()/get_children()/ get_pages() force suppress_filters=true and so never fire the_posts — the pre-query hook fires for every WP_Query regardless, so a plain foreach (get_posts(...) as $post) loop is covered too. Raw $wpdb queries are not (no query object to observe) — tag those explicitly. Page archives are excluded by default — adjust with the cachetags/autotag-excluded-archive-types filter. The header-size collapse keeps the broader tag set bounded.

Cacheability

Some responses must never be stored in a shared cache. Util::isCacheableRequest() returns false for previews and any request showing the admin bar (per-user chrome baked into the HTML), and — by default — for logged-in users. When a request is not cacheable the plugin skips tagging it and defines DONOTCACHEPAGE so page caches (WP Super Cache, Batcache, theme cache-control providers) don't store it; edge caches should consult Util::isCacheableRequest() from the theme/VCL since their TTL header is sent earlier.

Integrations hook the single cachetags/cacheable filter. Responses are vetoed at the default priority; opt-ins that re-enable logged-in users run earlier (priority <10) so the vetoes always win:

Nonces in cached pages

A page cached for hours can ship a stale nonce. WordPress nonces are valid for 12–24h; once one ages out, the action it guards (a form submit, an AJAX "load more", an add-to-cart) starts failing for everyone served the cached page.

Two ways to handle a page that bakes a nonce into its HTML:

  1. Tag it nonce. The page is then purged every 12 hours, before any embedded nonce can expire. The Nonce action runs that cron and is enabled by default, so you only need to add the tag where the nonce renders (the Gravityform action already does this for file-upload forms):

    Remove Nonce::class from the action config to opt out of the cron.

  2. Mark it non-cacheable when the page also shows genuinely real-time data (e.g. live availability), where a 12h refresh isn't enough:

Note that modern WooCommerce (10.7+) refetches the Store API nonce client-side before a write, so the sitewide Store API nonce is no longer a staleness risk on its own — only nonces that are actually used as rendered need this treatment.

Traits for use with roots/sage

Composers

ACF Blocks

Integrations

WooCommerce, Polylang & Gravity Forms (auto-enabled)

When WooCommerce, Polylang or Gravity Forms is active, its action is enabled automatically — you don't need to list it in action:

To manage the action list entirely yourself, turn detection off:

Flushing all pages, or a whole language

Every cacheable page and REST response carries a base page tag, so a single purge clears all WordPress-served pages at once — static assets (images/CSS/JS), which never carry it, stay cached:

Rename it or turn it off with 'base-tag' => null (config) / ->baseTag(null) (bootstrap).

When Polylang is active, every page is also tagged with its language, so you can clear all content in one language:

The Site action

On multisite where one edge (e.g. a single Fastly service) fronts the whole network, enable the Site action. It prefixes every tag with the site id (site:5:post:123) so a purge on one site never clears same-id content on another, and tags each page with site:{id} for a per-site flush-all (wp cachetags clear site:5). On a single site you don't need it — the base page tag above already gives flush-all without the per-tag prefixing.

Note the Site prefix also applies to the base tag, so with Site active the flush-all key is per-site site:5:page rather than the bare page.

Multisite tables

Each site has its own cache_tags table, provisioned on activation and when a new subsite is created. Run wp cachetags database to (re)scaffold every site — useful after activating on a large network where the activation request can't finish provisioning all of them.

CLI

With Acorn:

Standalone:

status answers "what's bloating the store / why was this purged so widely" — a tag with a high URL count purges that many pages on a single change. It requires a store that supports inspection (the default WordpressDbStore does).

prune garbage-collects store rows whose URL hasn't been rendered within the given age (12h/30d/4w) — query-string, bot and campaign-link variants that otherwise accumulate forever, especially on query-bypass edges. A row's age is last seen (refreshed on each render, at most once a day to avoid write churn), so actively-served pages are never pruned.

This runs daily by default (the prune-older-than config, default 30d) — the manual command above just forces a run. The age must exceed your edge cache's max TTL: pruning a URL still cached at the edge leaves an object you can no longer purge by tag (on Kinsta/Fastly the max TTL is ~30d, so raise it if your edge holds objects that long). Disable GC with 'prune-older-than' => null. Only a prunable store (the default WordpressDbStore) is affected — TransientStore no-ops.

The store is a rebuildable cache, so --rebuild migrates an existing (even million-row) table to the latest schema by dropping and recreating it — avoiding a slow, locking ALTER — and flushes the edge so nothing is left stale while the store refills. Run it in a low-traffic window; the cold cache warms as pages re-render.

API

Accessing CacheTags instance

With Acorn:

Standalone:

Building tags with Tag

Tags are Tag value objects — fluent to build, serialized to their string form (post:5, archive:post:any, site:5:term:9) only at the edge (header, store, purge). add() and clear() accept Tags, plain strings, and nested arrays interchangeably, so you rarely touch Tag directly — but it's there when you want type-safety or context.

Context is two general, composable operations — scope() to namespace a tag and qualify() for a variant — so new dimensions (a multisite network, a tenant) need no new API:

The builder classes (CoreTags, WooCommerceTags, SiteTags, PolylangTags, GravityformTags) return Tag[]; pass them — and any plain strings — straight to add()/clear(). Both take tags as individual arguments or arrays, nested freely:

Create a custom tag

The nicest way is to look at the code of this repo and create a custom Action, but the logic is really nothing more than:

With Acorn:

Standalone:


All versions of sage-cachetags with dependencies

PHP Build Version
Package Version
Requires php Version >=8.2
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package generoi/sage-cachetags contains the following files

Loading the files please wait ...