命令列模式 php -f script.php 觸發流程:
php_cli.c 處理 -f、-r、-i 等選項php_request_startup() 初始化模組、超全域變數php_execute_script() → zend_execute_scripts()php_request_shutdown()、模組 RSHUTDOWNzend_execute_scripts()ZEND_API void zend_execute_scripts(int type, zval *retval, int file_count, ...) {
va_list files;
va_start(files, file_count);
for (int i = 0; i < file_count; i++) {
zend_file_handle *fh = va_arg(files, zend_file_handle*);
// 1. 編譯
zend_op_array *op_array = zend_compile_file(fh, type);
// 2. 執行
if (op_array) {
zend_execute(op_array, retval);
destroy_op_array(op_array);
}
zend_destroy_file_handle(fh);
}
va_end(files);
}
zend_compile_file / zend_executecompile_file = dtrace_compile_file ?: zend_compilezend_execute 為 vld_execute,執行前 dump opcodezend_compile_file()zend_language_scanner.c → Token 序列zend_language_parser.y (Bison) → ASTzend_op_array:包含 opcode 陣列、常量表、變數名表、類/函數定義zend_execute()zend_vm_execute.h 巨型 switch(或 threaded dispatch)zval、棧框、符號表zend_execute_data,形成調用棧// 生成 opcode (php -d vld.active=1 -d vld.execute=0 -f test.php) /* 0 INIT_FCALL_BY_NAME 'echo' 1 ADD ~0, 1, 2 2 ASSIGN !0, ~0 3 SEND_VAR !0 4 DO_FCALL 1 5 RETURN 1 */
| 擴展 | 替換指針 | 用途 |
|---|---|---|
| opcache | zend_compile_file | 緩存編譯結果,跳過編譯 |
| xdebug | zend_execute | 逐行斷點、覆蓋率統計 |
| vld | zend_execute / zend_compile_file | 輸出 opcode 供分析 |
| phpdbg | zend_execute | 內建 SAPI 除錯器 |
PHP CLI 請求:參數解析 → 啟動 → zend_execute_scripts(compile_file + execute) → 關閉。zend_compile_file 與 zend_execute 兩大函數指針是 Zend 引擎留給擴展的核心擴展點,理解此機制即掌握 Opcode 緩存、除錯器、靜態分析工具的底層原理。