smart-core/accelerator-cache-bundle
Smart Core Accelerator Cache Bundle adds a fast, configurable caching layer to Symfony apps, helping reduce database load and speed up repeated requests with cache adapters, warmup, and simple integration.
First, the framing: despite the prompt, smart-core/accelerator-cache-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/accelerator.php, and no Artisan command. A Laravel developer has two realistic options: (a) use it inside a Symfony app (the intended use case), or (b) copy the ~20 lines of opcache_reset() / apc_clear_cache() logic into a Laravel command. Treat it as a reference implementation of a deploy-time cache-flush step.
Minimal steps (Symfony 3.x-era app, the target):
composer require smart-core/accelerator-cache-bundle
Register the bundle:
// app/AppKernel.php (Symfony 2/3)
$bundles = [
// ...
new SmartCore\Bundle\AcceleratorCacheBundle\AcceleratorCacheBundle(),
];
// config/bundles.php (Symfony 4+, if it loads at all)
SmartCore\Bundle\AcceleratorCacheBundle\AcceleratorCacheBundle::class => ['all' => true],
Then discover the command rather than guessing the name:
php bin/console list | grep -i acceler
# typically: cache:accelerator:clear
First use case: run it at the end of a deploy, right after bin/console cache:clear, so PHP-FPM workers don't keep serving stale opcode from the old release directory.
Where to look first in the repo: Resources/config/ for the service/command wiring, and the Command/ directory for the actual opcache_reset() / apc_clear_cache() calls. The whole package is small — read it in one sitting before depending on it.
Laravel equivalent (recommended path):
// app/Console/Commands/ClearOpcache.php
public function handle()
{
if (!function_exists('opcache_reset')) {
$this->warn('OPcache extension not loaded.');
return;
}
$this->line(opcache_reset() ? 'OPcache reset.' : 'OPcache reset failed.');
}
php artisan opcache:clear
# deploy.sh — order matters
php bin/console cache:clear --env=prod
php bin/console cache:accelerator:clear --env=prod
sudo systemctl reload php8.2-fpm # still usually needed, see Gotchas
Pair it with atomic symlink releases (releases/20240101... → current). Resetting opcache after the symlink swap is what makes new code visible; resetting before is wasted work.
If opcache.enable_cli=0 (the default), the CLI command only clears the CLI's own empty cache. Route the flush through the web SAPI instead:
// routes: /_ops/opcache-reset, protected by a token header + IP allowlist
Route::post('/_ops/opcache-reset', function (Request $request) {
abort_unless($request->header('X-Ops-Token') === config('ops.token'), 403);
return response()->json(['reset' => opcache_reset()]);
});
curl -fsS -X POST -H "X-Ops-Token: $TOKEN" https://app.example.com/_ops/opcache-reset
Full resets are blunt. For config/CSS/translation files generated at runtime, invalidate just the changed path:
opcache_invalidate('/var/www/current/bootstrap/cache/config.php', true);
Envoy.blade.php, deployer.php, or a CI step.php artisan octane:reload already reloads workers — that's usually sufficient and makes an explicit opcache reset redundant.appstract/laravel-opcache gives you artisan opcache:clear, opcache:compile, and opcache:status — a closer daily-driver to this bundle's purpose.$status = opcache_get_status(false);
// watch: opcache_statistics.hit_rate, oom_restarts, cached_scripts, max_cached_keys
Log hit_rate weekly; a sudden drop is your signal that the deployed files aren't being cached (wrong opcache.memory_consumption, or validate_timestamps churn).
The CLI/FPM separation trap — this is the #1 reason the bundle appears to "do nothing." opcache_reset() only affects the SAPI process it runs in. A console command cannot clear the opcache of a separate PHP-FPM pool. Options: set opcache.enable_cli=1 (helps only if the CLI and FPM share opcache.file_cache, which is niche), expose an HTTP reset endpoint, or just systemctl reload php-fpm. On Kubernetes/Docker, each replica has its own opcache — a rolling restart is the honest fix; there is no cluster-wide flush.
opcache.validate_timestamps=0 in production means file mtimes are never re-checked. Combined with a stale opcache, you'll deploy successfully and still serve the old class. Every deploy must reset or restart.
Preloading defeats the reset. If opcache.preload / opcache.preload_user is configured, preloaded scripts stay compiled for the life of the worker. Only an FPM reload clears them — opcache_reset() cannot.
APC ≠ APCu ≠ OPcache. apc_clear_cache() clears a user cache that has nothing to do with opcode. APCu is not the opcode cache; clearing it won't help with stale code. Verify which extension is actually active with php -m | grep -i -E 'opcache|apc' before trusting the command's output.
disable_functions and opcache.restrict_api can silently neuter the reset (it returns false or warns). Check the return value of opcache_reset() rather than assuming the command's exit 0 means success — Symfony commands commonly return 0 even on a non-fatal PHP warning.
Maintenance risk is the real gotcha. 67 stars, 0 dependents, no Flex recipe, no Symfony 5/6/7 support. It's a Symfony 2/3-era bundle: AppKernel-style registration, and likely hardcoded resources/config YAML that Flex won't autoload. Budget an hour to verify it even boots on a modern Symfony before it enters your deploy script. If it doesn't, the replacement is a 15-line custom command — do that instead of forking.
No config knobs worth learning. There's no meaningful bundle config; the behavior is "call the PHP function." Don't go looking for accelerator_cache.* options — they aren't there.
Extension point: the only useful customization is wrapping the bundled command/service and overriding configure() to add --no-warmup-style flags or to route through your own "flush endpoints per node" logic for multi-server deploys:
foreach (config('ops.nodes') as $node) {
Http::withHeaders(['X-Ops-Token' => config('ops.token')])
->post("https://{$node}/_ops/opcache-reset")
->throw();
}
Sanity check after any flush: opcache_get_status(false)['opcache_enabled'] should be true, and cached_scripts should climb back toward its previous count as traffic arrives. If it stays at zero, the reset ran in the wrong process.
How can I help you explore Laravel packages today?