PHP Compilation Pipeline
debt(d5/e3/b5/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list opcache-gui and blackfire — both specialist tools requiring deliberate instrumentation. A developer won't notice OPcache is disabled or that compilation is repeated on every request without profiling; standard linters don't flag this, but tools like blackfire will expose the parse/compile overhead in a flamegraph.
Closest to 'simple parameterised fix' (e3). The quick_fix describes understanding the pipeline and enabling OPcache — enabling OPcache is a config change (php.ini / opcache.enable=1) plus potentially a deployment step (cache:clear awareness). It's more than a single-line code patch but doesn't span multiple files architecturally; it's a targeted configuration correction.
Closest to 'persistent productivity tax' (b5). The concept applies to both web and CLI contexts across all PHP 5.0+ codebases. Misunderstanding the pipeline affects OPcache configuration decisions, deployment scripts (cache:clear), JIT tuning, and how developers reason about syntax errors — a persistent tax across multiple work streams rather than isolated to one component.
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field is explicit: developers assume PHP is interpreted line-by-line (a belief reinforced by scripting language analogies), but PHP compiles entire files to opcodes before executing any line. This contradicts the mental model imported from truly line-by-line interpreters, leading to consequential production mistakes like disabling OPcache or misunderstanding compile-time syntax errors.
Also Known As
TL;DR
Explanation
PHP execution pipeline: (1) Lexer: source text → token stream (T_FUNCTION, T_STRING, T_WHITESPACE). (2) Parser: tokens → Abstract Syntax Tree using LALR(1) grammar. (3) Compiler: AST → opcode array (zend_op structs — ZEND_ADD, ZEND_CALL, ZEND_RETURN). (4) Zend VM: executes the opcode array. OPcache intercepts after step 3: serialises compiled opcodes to shared memory — subsequent requests fetch opcodes directly, skipping steps 1-3. JIT (PHP 8.0+): OPcache's JIT further compiles hot opcodes to native x86/ARM machine code.
Common Misconception
Why It Matters
Common Mistakes
- Assuming PHP re-lexes and re-parses files on every request without OPcache
- Expecting syntax errors to appear lazily at the line they are on — errors appear at compile time
- Disabling OPcache in production — the single biggest PHP performance regression possible
- Thinking OPcache opcodes are the same as JIT-compiled native code — they are different stages
Code Examples
// Expecting lazy evaluation:
if (false) {
$x = 1 +; // Syntax error on this line
}
// Assumption: no error — dead branch
// Reality: PHP compiles the entire file first
// Fatal error: parse error, unexpected ';' — before any code executes
// OPcache eliminates recompilation:
// Request 1 (cold): lex → parse → compile → store in shared memory
// Request 2 (warm): fetch opcodes from shared memory → execute directly
// Speedup: skip ~90% of compilation work per request
// Verify OPcache is working:
$status = opcache_get_status();
// Healthy production: hit rate > 99%
// opcache_hit_rate = hits / (hits + misses)