
token_get_all() 对同一 PHP 代码(如 )返回不同 token 数组,根本原因在于 short_open_tag ini 配置项的启用状态差异——该设置直接影响 Zend 引擎的词法分析阶段,且运行时不可动态修改。
`token_get_all()` 对同一 php 代码(如 ` ?>`)返回不同 token 数组,根本原因在于 `short_open_tag` ini 配置项的启用状态差异——该设置直接影响 zend 引擎的词法分析阶段,且运行时不可动态修改。
token_get_all() 是 PHP 内置的底层词法分析工具,它并非简单地按字符串切分,而是复用 Zend 引擎的真实解析逻辑。这意味着其输出严格依赖于当前 PHP 运行环境的配置,尤其是 short_open_tag 这一关键开关。
当 short_open_tag = On 时, 被识别为合法的短开标签(T_OPEN_TAG),?> 被识别为短闭标签(T_CLOSE_TAG),中间空格则被单独切分为 T_WHITESPACE —— 因此 ?> 会被拆解为 3 个 token:
// short_open_tag = 1
var_export(token_get_all(' ?>'));
// 输出:
array (
0 => array(0 => T_OPEN_TAG, 1 => '', 2 => 1),
1 => array(0 => T_WHITESPACE, 1 => ' ', 2 => 1),
2 => array(0 => T_CLOSE_TAG, 1 => '?>', 2 => 1),
)
而当 short_open_tag = Off(默认推荐值,自 PHP 7.4+ 已默认关闭,PHP 8.0+ 彻底移除支持)时, 不再被识别为 PHP 标签,整段内容被视为纯 HTML/文本,归类为 T_INLINE_HTML —— 整个字符串仅生成 1 个 token:
// short_open_tag = 0
var_export(token_get_all(' ?>'));
// 输出:
array (
0 => array(0 => T_INLINE_HTML, 1 => ' ?>', 2 => 1),
)
⚠️ 注意:
short_open_tag是编译期/启动期配置,无法在脚本中通过ini_set()修改。调用token_get_all()前,其行为已由 PHP 启动时加载的php.ini或命令行参数(如-d short_open_tag=0)完全确定。
实际开发建议
坚持使用标准标签
为保障代码可移植性(跨环境、跨版本、跨工具链),应彻底避免和等非标准短标签,统一使用<?php和=。这是 PSR-12、PHP-FIG 及主流静态分析工具(如 PHP-CS-Fixer、PHPStan)的通用要求。-
在 PhpCS 中主动拦截
启用内置规则强制检查:# 检测短标签(需确保 PhpCS 运行环境 short_open_tag=On,否则无法识别) phpcs --standard=Generic --sniffs=Generic.PHP.DisallowShortOpenTag your-file.php # 自动修复(推荐) phpcbf --standard=Generic --sniffs=Generic.PHP.DisallowShortOpenTag your-file.php
-
CI/CD 与 Docker 中显式控制
在容器或 CI 配置中明确禁用短标签,消除环境不确定性:# Dockerfile 片段 RUN echo "short_open_tag = Off" >> /usr/local/etc/php/conf.d/docker-php-ext-short-tag.ini
# .github/workflows/ci.yml 片段 - name: Run PHP CS run: php -d short_open_tag=0 vendor/bin/phpcs ...
-
替代方案:使用
PhpToken(PHP 8.0+)
若项目已升级至 PHP 8.0+,推荐迁移到更现代、类型安全的PhpToken::tokenize(),它返回标准化对象数组,API 更清晰,且同样受short_open_tag影响,但大幅降低手动解析风险:$tokens = PhpToken::tokenize(' ?>'); foreach ($tokens as $token) { echo $token->getTokenName() . ': "' . $token->text . '"' . PHP_EOL; }
总之,token_get_all() 的“不一致”并非 Bug,而是其设计本质:它忠实地反映当前 PHP 解析器的行为。真正的工程实践不是适配配置差异,而是通过规范编码习惯 + 工具链约束,主动消除歧义源头。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











