Backend Development 5 min read

Why PHP OpCache Fails with Symlinks and How to Fix It

A PHP backend team discovered that enabling OpCache with a symlinked project caused the new version to be ignored, traced the issue to cached file paths, and resolved it by adjusting Nginx fastcgi parameters to use the real path, restoring proper deployment behavior.

360 Zhihui Cloud Developer
360 Zhihui Cloud Developer
360 Zhihui Cloud Developer
Why PHP OpCache Fails with Symlinks and How to Fix It

During a routine release, a colleague noticed that the new version of a PHP application did not take effect after deployment. Initial checks of code and server configuration revealed no obvious problems, but the issue disappeared after restarting PHP‑FPM, suggesting OpCache involvement.

Further investigation showed that disabling OpCache allowed the new version to work, confirming that OpCache was the culprit. The team examined the stack trace, which included an exception indicating a missing controller file:

<code>exception 'QFrameRunException' with message 'Controller File('/home/q/server/project_1002/src/application/controllers/1Controller.php') is Not Exist!!!'
 in /home/q/php/QFrame/base/QFrameutils.php:114
Stack trace:
#0 /home/q/php/QFrame/web/QFrameweb.php(168): QFrameBizResult::ensureNotFalse(false, 'Controller File...')
#1 /home/q/php/QFrame/web/QFrameweb.php(150): QFrameWeb->dispatch()
#2 /home/q/php/QFrame/web/QFrameweb.php(129): QFrameWeb->runController('1')
#3 /home/q/php/QFrame/web/QFrameweb.php(37): QFrameWeb->processRequest()
#4 /home/q/server/project_1001/src/www/index.php(13): QFrameWeb->run()
#5 {main}</code>

The root cause was identified as the combination of OpCache and a symlinked project directory. OpCache caches the compiled opcode arrays keyed by the real file path (e.g., /home/q/server/project_1001/src/www/index.php ). When the project directory was switched from project_1001 to project_1002 via a symlink, the fastcgi parameters SCRIPT_FILENAME and DOCUMENT_ROOT still pointed to the old path, so OpCache continued to serve the cached version.

Fixing the issue required modifying the Nginx fastcgi configuration to use the real path variable $realpath_root :

<code>fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;</code>

With these changes, the path changes when the symlink target changes, forcing OpCache to re‑cache the correct files and allowing the new version to be served.

The problem was reproduced on PHP 5.5; other PHP versions may behave similarly. The original author of PHP, Rasmus Lerdorf, discussed related solutions on GitHub, especially for cases involving relative paths and Apache servers.

Reference: https://github.com/zendtech/ZendOptimizerPlus/issues/126

backendperformancePHPNginxSymlinkOpCache
360 Zhihui Cloud Developer
Written by

360 Zhihui Cloud Developer

360 Zhihui Cloud is an enterprise open service platform that aims to "aggregate data value and empower an intelligent future," leveraging 360's extensive product and technology resources to deliver platform services to customers.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.