Skip to main content
Caching avoids repeating expensive setup work on every workflow run. There are two main things worth caching in a PHP workflow: compiled PHP extensions and Composer’s package download cache.

Extension caching

Some PHP extensions take a long time to compile and install. You can cache them using the shivammathur/cache-extensions action together with actions/cache. When the cache is warm, extensions are enabled directly from the cache instead of being compiled again, which significantly reduces setup time.
The shivammathur/cache-extensions action must run before setup-php so that the cache is restored before PHP setup begins. Refer to the cache-extensions documentation for full configuration options.

Composer dependency caching

Composer maintains an internal download cache separate from the vendor directory. Caching this directory means packages are loaded from disk instead of being downloaded from Packagist on every run.

Basic setup with composer.lock

When you commit composer.lock, use its hash as the cache key. This ensures the cache is invalidated whenever your locked dependencies change.

When there is no composer.lock

If you do not commit composer.lock (common for libraries), use the hash of composer.json instead:

Using prefer-lowest and prefer-stable in cache keys

If your matrix tests both minimum and stable dependency versions, include the preference in your cache key so the two variants do not share a cache:
Do not cache the vendor directory using actions/cache. Caching vendor can cause subtle issues because generated files, platform-specific binaries, and autoloader state inside vendor are not portable across runners. Always cache Composer’s internal download cache (the path returned by composer config cache-files-dir) and run composer install to reconstruct vendor.

Complete workflow example

The following workflow combines PHP setup, extension caching, and Composer dependency caching: