orkestra/apc-bundle
A small bundle that adds APC/APCu cache support to Orkestra applications, wiring cache services and configuration so PHP's shared memory cache can be used through the framework's standard cache abstractions. Useful for fast local caching without external services.
Before anything else: this is a Symfony 2 bundle, not a Laravel package. There is no service provider, no extra.laravel auto-discovery, no config/apc.php, and none of its classes implement Laravel's Illuminate\Contracts\Cache\Repository. "Leveraging it day-to-day" therefore means one of two things, and you should decide which on minute one:
Cache facade + apcu_* functions). Do not composer require it; the APC extension it targets does not exist on supported PHP.Minimal steps for case 1 (legacy Symfony 2):
composer require orkestra/apc-bundle
// app/AppKernel.php
public function registerBundles()
{
return [
// ...
new Orkestra\Bundle\ApcBundle\OrkestraApcBundle(),
];
}
Where to look first, in this order:
DependencyInjection/Configuration.php and ...Extension.php — the real config tree and every tunable lives here. On a 4-star Symfony 2-era bundle the README is almost always stale; the Configuration class is the source of truth for the prefix/extension options.Resources/config/services.xml — the actual service IDs you will inject or override. Match these against your app/config/config.yml override keys.composer.json — the symfony/symfony constraint pins which Symfony 2 minor you can be on. Read this before upgrading anything.Your first real use case will be deploy-time cache invalidation: after every release you need apc_clear_cache('user') equivalent triggered from the framework, not from a shell. That is the core thing this bundle wires up, and it is the first thing to verify works end to end before touching anything else.
Pattern 1 — Inject the cache service, never call apc_* directly. The whole point of the bundle is that cache access goes through a configured service, so prefix and extension are centralized. Inject the service by ID from services.xml into your controllers/repositories and let the bundle own the apc_fetch/apc_store calls. If you find yourself writing apc_fetch() in application code, you have bypassed the abstraction and lost the ability to swap backends later.
Pattern 2 — Prefix per app/environment. Use the configurable cache prefix to namespace keys by environment and service (prod_billing_, staging_billing_). This makes shared single-server FPM pools predictable and lets you invalidate one concern without nuking the whole user cache.
Pattern 3 — Deploy hook for warm-up + clear. Standard workflow for a released Symfony 2 app:
git pull -> cache:clear -> apc clear (via bundle service) -> warm cache -> reload php-fpm
Wire the APC clear into your deploy script (Capistrano/Envoy/whatever) using a Symfony console command that calls the bundle service. On a single host this is coherent; see Gotchas for why it stops being coherent the moment you scale out.
Pattern 4 — Cache only what is expensive and idempotent. Configuration trees, route collections, annotation/Doctrine metadata, and rendered fragments — the classical Symfony 2 hot spots. Do not cache session-scoped or user-specific data in a per-process APC store; you will get cross-request bleed under FPM workers if keys aren't carefully composed.
Pattern 5 (Laravel teams) — Reimplement, don't wrap. If the value you want is "show me APC/APCu hit ratios and let me flush," write it natively:
// app/Console/Commands/CacheStats.php — the honest Laravel replacement
if (! function_exists('apcu_cache_info')) {
$this->error('APCu extension not loaded'); return;
}
$info = apcu_cache_info(); // hits, misses, num_entries, mem_size
// surface in a dashboard; flush with apcu_clear_cache()
Point Laravel's config/cache.php at the apc/array store for the same effect on a single host, and at Redis/Memcached the moment you have more than one node.
Integration tip: bind the bundle's cache service into your domain services via constructor injection rather than reaching for the container ($this->get('...')). Symfony 2 lets you do the latter, but it makes the eventual rip-out into symfony/cache far more painful.
apc_* calls imply plain APC, which has not built since PHP 5.x. On any modern runtime you have apcu_* instead, and the bundle will fatal on the missing extension rather than degrade gracefully. Confirm extension availability with php -m | grep -i apc before you debug anything else.cache:clear run from the command line does not clear the FPM worker's user cache. This produces the classic "cleared the cache, still stale in the browser" bug. Always clear in the SAPI that serves traffic (a web-exposed clear endpoint, or restart FPM).apc_store fails quietly. Your app keeps working, just uncached and suddenly slow. Instrument apcu_cache_info()/apcu_sma_info() and alert on misses and fragmentation rather than waiting for a user to report latency.apc.shm_size / apcu.shm_size). It does not grow. Under sustained load you will see fragmentation and eventual allocation failures needing a worker restart. Tune ini values, and size for peak, not average.php -m for the extension, (2) DependencyInjection/Configuration.php for the real config key (README lies), (3) Resources/config/services.xml for the correct service ID (typos here give "service not found", not a cache miss), (4) confirm the prefix matches between write and read. Ninety percent of "it's not caching" reports are one of these four.symfony/cache (Symfony 3+) or Laravel's native drivers, which is where the day-to-day value actually lives.symfony/cache (PSR-6/PSR-16) or Cache facade + Redis, and let this bundle serve only the paths that already use it, frozen.How can I help you explore Laravel packages today?