From 6b7eb67548454e0412f6204bfc32f1a271027f22 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Mon, 27 Jul 2026 22:46:36 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96$=5FSERVER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Translator.php | 35 ++++++++++++++++++++ tests/compiler/super_global/server-init.phpt | 17 ++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/compiler/super_global/server-init.phpt diff --git a/src/Translator.php b/src/Translator.php index 542d0278..a23d2383 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -690,6 +690,15 @@ class Translator extends Preprocessor { $lines[] = '#include '; $lines[] = PHP_EOL; + + /** + * 当程序启动后,PHP_SELF,SCRIPT_NAME,SCRIPT_FILENAME,PATH_TRANSLATED,DOCUMENT_ROOT + * 这些属性不会出现在$_SERVER中,因此我们需要手动生成。所以必须生成$_SERVER的声明。 + */ + if (!isset($this->globalVars['_SERVER'])) { + $this->globalVars['_SERVER'] = Type::ARRAY; + } + foreach ($this->globalVars as $name => $type) { $lines[] = 'extern THREAD_LOCAL ' . Type::VAR . ' ' . $this->escapeGlobalVar($name) . ';'; } @@ -3205,6 +3214,10 @@ CODE; $callParams = $functionDef->argInfoList ? rtrim($callParams, ',') : ''; } + if (!$functionDef->method && strtolower($functionDef->name) == 'main') { + $cppCode .= $this->registerServerEnvironment($functionDef->sourceFile); + } + if ($functionDef->returnType !== Type::VOID) { $cppCode .= $this->getIndent() . 'auto retval = ' . $fn . '(' . $callParams . ');' . PHP_EOL; $cppCode .= $this->getIndent() . 'php::move(retval, return_value);' . PHP_EOL; @@ -3219,6 +3232,28 @@ CODE; return $cppCode; } + /** + * 在main函数中,将PHP_SELF,SCRIPT_NAME,SCRIPT_FILENAME和DOCUMENT_ROOT写入 + * $_SERVER中,这些属性相当于初始化,所以不需要常驻内存。 + * 默认main函数所在的文件名就是脚本文件名字。 + */ + private function registerServerEnvironment(string $scriptName): string + { + $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL;; + $cppCode .= 'php::Str php_self = "PHP_SELF";' . PHP_EOL; + $cppCode .= 'php::Str script_name = "SCRIPT_NAME";' . PHP_EOL; + $cppCode .= 'php::Str script_filename = "SCRIPT_FILENAME";' . PHP_EOL; + $cppCode .= 'php::Str document_root = "DOCUMENT_ROOT";' . PHP_EOL; + $cppCode .= 'php::Str value = "' . $scriptName . '";' . PHP_EOL; + + $cppCode .= '_SERVER.item(php_self, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(script_name, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(script_filename, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(document_root, true) = "";' . PHP_EOL; + + return $cppCode . PHP_EOL; + } + private function canConsumeForwardedArgument(ArgInfo $argInfo): bool { if ($argInfo->byRef) { diff --git a/tests/compiler/super_global/server-init.phpt b/tests/compiler/super_global/server-init.phpt new file mode 100644 index 00000000..0ac538a6 --- /dev/null +++ b/tests/compiler/super_global/server-init.phpt @@ -0,0 +1,17 @@ +--TEST-- +$_SERVER: init PHP_SELF, SCRIPT_NAME, SCRIPT_FILENAME, PATH_TRANSLATED and DOCUMENT_ROOT +--FILE-- + +--EXPECT-- From 50cd78772c6152c09cd0d50e883ff6f3cf35f9ad Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 30 Jul 2026 19:02:31 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96$=5FSERVER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Translator.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Translator.php b/src/Translator.php index a23d2383..36dd955f 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -692,8 +692,10 @@ class Translator extends Preprocessor $lines[] = PHP_EOL; /** - * 当程序启动后,PHP_SELF,SCRIPT_NAME,SCRIPT_FILENAME,PATH_TRANSLATED,DOCUMENT_ROOT - * 这些属性不会出现在$_SERVER中,因此我们需要手动生成。所以必须生成$_SERVER的声明。 + * 由于编译后的PHP二进制程序无需再指定入口文件,$_SERVER 中原本依赖入口文件才能生成的超全局变量( + * 如 PHP_SELF、SCRIPT_NAME、SCRIPT_FILENAME 和 DOCUMENT_ROOT)将不会被自动生成。 + * 然而,部分框架的初始化逻辑强依赖这些参数,缺失将导致启动失败。因此,我们必须在入口函数中手动为 $_SERVER 补充这些值。 + * 但需要注意的是,$_SERVER 必须事先声明,否则无法向其写入内容。 */ if (!isset($this->globalVars['_SERVER'])) { $this->globalVars['_SERVER'] = Type::ARRAY; @@ -3233,9 +3235,12 @@ CODE; } /** - * 在main函数中,将PHP_SELF,SCRIPT_NAME,SCRIPT_FILENAME和DOCUMENT_ROOT写入 - * $_SERVER中,这些属性相当于初始化,所以不需要常驻内存。 - * 默认main函数所在的文件名就是脚本文件名字。 + * 由于编译后的PHP二进制程序无需再指定入口文件,$_SERVER 中依赖入口文件才能生成的超全局变量 + * (如 PHP_SELF、SCRIPT_NAME、SCRIPT_FILENAME 和 DOCUMENT_ROOT)将被忽略。 + * 但部分PHP框架依赖这些参数完成初始化逻辑,缺少它们将导致启动失败。因此,我们需在入口函数中 + * 手动为 $_SERVER 补充这些值,默认以 main 函数所在文件作为入口文件。 + * @param string $scriptName + * @return string */ private function registerServerEnvironment(string $scriptName): string { From cbfdd248f09fa720324cc32b349eeabad88a53a3 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 30 Jul 2026 20:23:10 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Translator.php | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/Translator.php b/src/Translator.php index 36dd955f..68dd1486 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -1057,6 +1057,9 @@ CODE; } else { $entryScript = $entryPrefix . 'main();'; } + + // 手动设置 $_SERVER 仅在 PHP 作为可运行二进制运行时才有意义;对于 .so 扩展,$_SERVER 由 SAPI 自动管理,不应在扩展层覆盖。 + $code .= $this->registerServerEnvironment($entryFileArg); $code .= 'php::eval(' . $this->genCharPtr($entryScript, true) . ', ' . $entryFileArg . ');' . PHP_EOL; } @@ -3216,10 +3219,6 @@ CODE; $callParams = $functionDef->argInfoList ? rtrim($callParams, ',') : ''; } - if (!$functionDef->method && strtolower($functionDef->name) == 'main') { - $cppCode .= $this->registerServerEnvironment($functionDef->sourceFile); - } - if ($functionDef->returnType !== Type::VOID) { $cppCode .= $this->getIndent() . 'auto retval = ' . $fn . '(' . $callParams . ');' . PHP_EOL; $cppCode .= $this->getIndent() . 'php::move(retval, return_value);' . PHP_EOL; @@ -3245,16 +3244,12 @@ CODE; private function registerServerEnvironment(string $scriptName): string { $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL;; - $cppCode .= 'php::Str php_self = "PHP_SELF";' . PHP_EOL; - $cppCode .= 'php::Str script_name = "SCRIPT_NAME";' . PHP_EOL; - $cppCode .= 'php::Str script_filename = "SCRIPT_FILENAME";' . PHP_EOL; - $cppCode .= 'php::Str document_root = "DOCUMENT_ROOT";' . PHP_EOL; - $cppCode .= 'php::Str value = "' . $scriptName . '";' . PHP_EOL; - - $cppCode .= '_SERVER.item(php_self, true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item(script_name, true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item(script_filename, true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item(document_root, true) = "";' . PHP_EOL; + $cppCode .= 'php::Str value =' . $scriptName . ';' . PHP_EOL; + + $cppCode .= '_SERVER.item("PHP_SELF", true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item("SCRIPT_NAME", true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item("SCRIPT_FILENAME", true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item("DOCUMENT_ROOT", true) = "";' . PHP_EOL; return $cppCode . PHP_EOL; } From a4af1b294c48ae8a9bb9235980fb31403bb13841 Mon Sep 17 00:00:00 2001 From: NathanFreeman <1056159381@qq.com> Date: Thu, 30 Jul 2026 21:13:01 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Translator.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Translator.php b/src/Translator.php index 68dd1486..a667a0cc 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -3243,7 +3243,8 @@ CODE; */ private function registerServerEnvironment(string $scriptName): string { - $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL;; + $cppCode = PHP_EOL; + $cppCode .= 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL;; $cppCode .= 'php::Str value =' . $scriptName . ';' . PHP_EOL; $cppCode .= '_SERVER.item("PHP_SELF", true) = value;' . PHP_EOL; From 42306455492b41dc0888ad4f95747a0564820fe1 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 30 Jul 2026 18:01:07 +0800 Subject: [PATCH 5/8] fix: align server globals with PHP CLI --- phpunit/src/ServerEnvironmentTest.php | 72 ++++++++++++++++++++ src/Translator.php | 42 +++++------- tests/compiler/super_global/server-init.phpt | 15 ++-- 3 files changed, 99 insertions(+), 30 deletions(-) create mode 100644 phpunit/src/ServerEnvironmentTest.php diff --git a/phpunit/src/ServerEnvironmentTest.php b/phpunit/src/ServerEnvironmentTest.php new file mode 100644 index 00000000..54697ee8 --- /dev/null +++ b/phpunit/src/ServerEnvironmentTest.php @@ -0,0 +1,72 @@ +testDir = sys_get_temp_dir() . '/server_environment_test_' . uniqid(); + mkdir($this->testDir, 0777, true); + } + + protected function tearDown(): void + { + parent::tearDown(); + $this->removeDirectory($this->testDir); + } + + private function removeDirectory(string $dir): void + { + if (!is_dir($dir)) { + return; + } + foreach (array_diff(scandir($dir), ['.', '..']) as $file) { + $path = $dir . DIRECTORY_SEPARATOR . $file; + is_dir($path) ? $this->removeDirectory($path) : unlink($path); + } + rmdir($dir); + } + + public function testGeneratedServerEnvironmentMatchesCliAndEscapesScriptPath(): void + { + $compiler = CompilerTest::create($this->testDir); + $method = new ReflectionMethod(Translator::class, 'registerServerEnvironment'); + $code = $method->invoke($compiler, 'C:\\project\\"quoted"\\main.php'); + + $this->assertStringContainsString('php::Str php_self = "PHP_SELF";', $code); + $this->assertStringContainsString('php::Str script_name = "SCRIPT_NAME";', $code); + $this->assertStringContainsString('php::Str script_filename = "SCRIPT_FILENAME";', $code); + $this->assertStringContainsString('php::Str path_translated = "PATH_TRANSLATED";', $code); + $this->assertStringContainsString('php::Str document_root = "DOCUMENT_ROOT";', $code); + $this->assertStringContainsString( + 'php::Str value = "' . $compiler->escapeString('C:\\project\\"quoted"\\main.php') . '";', + $code + ); + $this->assertStringContainsString('_SERVER.item(path_translated, true) = value;', $code); + $this->assertStringContainsString('_SERVER.item(document_root, true) = "";', $code); + } + + public function testServerGlobalIsForcedOnlyForBinaryBuilds(): void + { + $binaryCompiler = CompilerTest::create($this->testDir); + $binaryFile = $this->testDir . '/binary.h'; + $binaryCompiler->genDataDeclarations($binaryFile); + $this->assertStringContainsString('_global_var__SERVER', file_get_contents($binaryFile)); + + $extensionCompiler = CompilerTest::create($this->testDir); + $extensionCompiler->setBuildMode(CompilerBase::BUILD_MODE_EXT); + $extensionFile = $this->testDir . '/extension.h'; + $extensionCompiler->genDataDeclarations($extensionFile); + $this->assertStringNotContainsString('_global_var__SERVER', file_get_contents($extensionFile)); + } +} diff --git a/src/Translator.php b/src/Translator.php index a667a0cc..335771d7 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -691,13 +691,9 @@ class Translator extends Preprocessor $lines[] = '#include '; $lines[] = PHP_EOL; - /** - * 由于编译后的PHP二进制程序无需再指定入口文件,$_SERVER 中原本依赖入口文件才能生成的超全局变量( - * 如 PHP_SELF、SCRIPT_NAME、SCRIPT_FILENAME 和 DOCUMENT_ROOT)将不会被自动生成。 - * 然而,部分框架的初始化逻辑强依赖这些参数,缺失将导致启动失败。因此,我们必须在入口函数中手动为 $_SERVER 补充这些值。 - * 但需要注意的是,$_SERVER 必须事先声明,否则无法向其写入内容。 - */ - if (!isset($this->globalVars['_SERVER'])) { + // Embedded binaries populate the CLI script fields in $_SERVER at + // request startup, even when the source does not reference $_SERVER. + if ($this->isBuildModeBin() && !isset($this->globalVars['_SERVER'])) { $this->globalVars['_SERVER'] = Type::ARRAY; } @@ -1050,6 +1046,7 @@ CODE; if ($this->isBuildModeBin()) { $entryFunction = $this->symbols->function(self::ENTRY_FUNCTION); $entryFile = $entryFunction->sourceFile; + $code .= $this->registerServerEnvironment($entryFile); $entryFileArg = $this->genCharPtr($entryFile, true); $entryPrefix = str_repeat("\n", max(0, $entryFunction->startLine - 1)); if (count($entryFunction->argInfoList) == 2) { @@ -1058,8 +1055,6 @@ CODE; $entryScript = $entryPrefix . 'main();'; } - // 手动设置 $_SERVER 仅在 PHP 作为可运行二进制运行时才有意义;对于 .so 扩展,$_SERVER 由 SAPI 自动管理,不应在扩展层覆盖。 - $code .= $this->registerServerEnvironment($entryFileArg); $code .= 'php::eval(' . $this->genCharPtr($entryScript, true) . ', ' . $entryFileArg . ');' . PHP_EOL; } @@ -3233,24 +3228,21 @@ CODE; return $cppCode; } - /** - * 由于编译后的PHP二进制程序无需再指定入口文件,$_SERVER 中依赖入口文件才能生成的超全局变量 - * (如 PHP_SELF、SCRIPT_NAME、SCRIPT_FILENAME 和 DOCUMENT_ROOT)将被忽略。 - * 但部分PHP框架依赖这些参数完成初始化逻辑,缺少它们将导致启动失败。因此,我们需在入口函数中 - * 手动为 $_SERVER 补充这些值,默认以 main 函数所在文件作为入口文件。 - * @param string $scriptName - * @return string - */ private function registerServerEnvironment(string $scriptName): string { - $cppCode = PHP_EOL; - $cppCode .= 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL;; - $cppCode .= 'php::Str value =' . $scriptName . ';' . PHP_EOL; - - $cppCode .= '_SERVER.item("PHP_SELF", true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item("SCRIPT_NAME", true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item("SCRIPT_FILENAME", true) = value;' . PHP_EOL; - $cppCode .= '_SERVER.item("DOCUMENT_ROOT", true) = "";' . PHP_EOL; + $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL; + $cppCode .= 'php::Str php_self = "PHP_SELF";' . PHP_EOL; + $cppCode .= 'php::Str script_name = "SCRIPT_NAME";' . PHP_EOL; + $cppCode .= 'php::Str script_filename = "SCRIPT_FILENAME";' . PHP_EOL; + $cppCode .= 'php::Str path_translated = "PATH_TRANSLATED";' . PHP_EOL; + $cppCode .= 'php::Str document_root = "DOCUMENT_ROOT";' . PHP_EOL; + $cppCode .= 'php::Str value = ' . $this->genCharPtr($scriptName, true) . ';' . PHP_EOL; + + $cppCode .= '_SERVER.item(php_self, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(script_name, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(script_filename, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(path_translated, true) = value;' . PHP_EOL; + $cppCode .= '_SERVER.item(document_root, true) = "";' . PHP_EOL; return $cppCode . PHP_EOL; } diff --git a/tests/compiler/super_global/server-init.phpt b/tests/compiler/super_global/server-init.phpt index 0ac538a6..8dd97750 100644 --- a/tests/compiler/super_global/server-init.phpt +++ b/tests/compiler/super_global/server-init.phpt @@ -1,16 +1,21 @@ --TEST-- $_SERVER: init PHP_SELF, SCRIPT_NAME, SCRIPT_FILENAME, PATH_TRANSLATED and DOCUMENT_ROOT +--ENV-- +PHP_SELF=from-environment +SCRIPT_NAME=from-environment +SCRIPT_FILENAME=from-environment +PATH_TRANSLATED=from-environment +DOCUMENT_ROOT=from-environment --FILE-- From 620c9e2ab1ad4a4e719a977acb29ddcaab7d0ae4 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 30 Jul 2026 18:01:07 +0800 Subject: [PATCH 6/8] fix: align server globals with PHP CLI --- src/Translator.php | 6 ++++-- tests/compiler/super_global/server-init.phpt | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Translator.php b/src/Translator.php index 335771d7..6faa767d 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -1045,6 +1045,8 @@ CODE; if ($this->isBuildModeBin()) { $entryFunction = $this->symbols->function(self::ENTRY_FUNCTION); + // FunctionDef::sourceFile comes from loadFile()'s realpath(), so the + // CLI script fields always identify main()'s canonical absolute file. $entryFile = $entryFunction->sourceFile; $code .= $this->registerServerEnvironment($entryFile); $entryFileArg = $this->genCharPtr($entryFile, true); @@ -3228,7 +3230,7 @@ CODE; return $cppCode; } - private function registerServerEnvironment(string $scriptName): string + private function registerServerEnvironment(string $entryFile): string { $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL; $cppCode .= 'php::Str php_self = "PHP_SELF";' . PHP_EOL; @@ -3236,7 +3238,7 @@ CODE; $cppCode .= 'php::Str script_filename = "SCRIPT_FILENAME";' . PHP_EOL; $cppCode .= 'php::Str path_translated = "PATH_TRANSLATED";' . PHP_EOL; $cppCode .= 'php::Str document_root = "DOCUMENT_ROOT";' . PHP_EOL; - $cppCode .= 'php::Str value = ' . $this->genCharPtr($scriptName, true) . ';' . PHP_EOL; + $cppCode .= 'php::Str value = ' . $this->genCharPtr($entryFile, true) . ';' . PHP_EOL; $cppCode .= '_SERVER.item(php_self, true) = value;' . PHP_EOL; $cppCode .= '_SERVER.item(script_name, true) = value;' . PHP_EOL; diff --git a/tests/compiler/super_global/server-init.phpt b/tests/compiler/super_global/server-init.phpt index 8dd97750..ce8cc049 100644 --- a/tests/compiler/super_global/server-init.phpt +++ b/tests/compiler/super_global/server-init.phpt @@ -12,10 +12,12 @@ DOCUMENT_ROOT=from-environment function main() { require __DIR__ . '/../../../src/Assert.php'; - Assert::eq($_SERVER['PHP_SELF'], __FILE__); - Assert::eq($_SERVER['SCRIPT_NAME'], __FILE__); - Assert::eq($_SERVER['SCRIPT_FILENAME'], __FILE__); - Assert::eq($_SERVER['PATH_TRANSLATED'], __FILE__); + $entryFile = realpath(__FILE__); + Assert::true(is_string($entryFile)); + Assert::eq($_SERVER['PHP_SELF'], $entryFile); + Assert::eq($_SERVER['SCRIPT_NAME'], $entryFile); + Assert::eq($_SERVER['SCRIPT_FILENAME'], $entryFile); + Assert::eq($_SERVER['PATH_TRANSLATED'], $entryFile); Assert::eq($_SERVER['DOCUMENT_ROOT'], ''); } ?> From d7de18f99350d43a81400c697b6b7b73267d9ee1 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 30 Jul 2026 18:01:07 +0800 Subject: [PATCH 7/8] fix: align server globals with PHP CLI --- src/Translator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Translator.php b/src/Translator.php index 6faa767d..cc5b5baa 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -693,8 +693,8 @@ class Translator extends Preprocessor // Embedded binaries populate the CLI script fields in $_SERVER at // request startup, even when the source does not reference $_SERVER. - if ($this->isBuildModeBin() && !isset($this->globalVars['_SERVER'])) { - $this->globalVars['_SERVER'] = Type::ARRAY; + if ($this->isBuildModeBin() && !$this->hasGlobalVar('_SERVER')) { + $this->addGlobalVar('_SERVER', Type::ARRAY); } foreach ($this->globalVars as $name => $type) { From ddc52ae3f6c0def2568823ef866317ad50b9ed46 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 30 Jul 2026 21:31:09 +0800 Subject: [PATCH 8/8] fix: generate server global symbol consistently --- phpunit/src/ServerEnvironmentTest.php | 1 + src/Translator.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/phpunit/src/ServerEnvironmentTest.php b/phpunit/src/ServerEnvironmentTest.php index 54697ee8..38f2b1e1 100644 --- a/phpunit/src/ServerEnvironmentTest.php +++ b/phpunit/src/ServerEnvironmentTest.php @@ -43,6 +43,7 @@ class ServerEnvironmentTest extends TestCase $method = new ReflectionMethod(Translator::class, 'registerServerEnvironment'); $code = $method->invoke($compiler, 'C:\\project\\"quoted"\\main.php'); + $this->assertStringContainsString('php::Var &_SERVER = _global_var__SERVER;', $code); $this->assertStringContainsString('php::Str php_self = "PHP_SELF";', $code); $this->assertStringContainsString('php::Str script_name = "SCRIPT_NAME";', $code); $this->assertStringContainsString('php::Str script_filename = "SCRIPT_FILENAME";', $code); diff --git a/src/Translator.php b/src/Translator.php index cc5b5baa..54eb22f1 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -3232,7 +3232,7 @@ CODE; private function registerServerEnvironment(string $entryFile): string { - $cppCode = 'php::Var &_SERVER = _global_var__SERVER;' . PHP_EOL; + $cppCode = 'php::Var &_SERVER = ' . $this->escapeGlobalVar('_SERVER') . ';' . PHP_EOL; $cppCode .= 'php::Str php_self = "PHP_SELF";' . PHP_EOL; $cppCode .= 'php::Str script_name = "SCRIPT_NAME";' . PHP_EOL; $cppCode .= 'php::Str script_filename = "SCRIPT_FILENAME";' . PHP_EOL;