什么是PHP中的__halt_compiler?

com*_*ler 46 php

手册:

void __halt_compiler ( void )
Run Code Online (Sandbox Code Playgroud)

该函数停止执行编译器.这对于在PHP脚本中嵌入数据非常有用,例如安装文件.

注意:__halt_compiler()只能从最外层范围使用.

任何人都可以提供这个功能有用的实际案例吗?

edo*_*ian 57

假设你有一个带有一些PHP代码和大量二进制混乱的脚本.

<?php doStuff(); __halt_compliler(); [BIG_BINARY_MESS]
Run Code Online (Sandbox Code Playgroud)

那么你希望编译器不要尝试解析二进制文件,因为如果二进制文件中的<?某个地方它会破坏.

关键是能够只发送一个包含二进制数据和PHP代码的文件.

有关小例子,请参阅此博文


因此,您不仅要停止execution脚本(如果exit()愿意),而且要停止脚本,parsing以便在文件末尾可以使用"无效语法",php仍然可以执行第一部分.


另一个例子:

这将被解析为有效的PHP并执行得很好:

<?php $a = 1; echo $a; __halt_compiler(); §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();
Run Code Online (Sandbox Code Playgroud)

要访问数据:

<?php
$file = fopen(__FILE__, 'rb');
// Go to the end of the __halt_compiler();
fseek($file, __COMPILER_HALT_OFFSET__);
echo stream_get_contents($file);
__halt_compiler(); §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();
Run Code Online (Sandbox Code Playgroud)

这将输出 §RW$FG$%ZDS$TSG$TSZ%U(); §$"§%"§$!!();

  • 如何使用`§RW$ FG $%ZDS $ TSG $ TSZ%U(); §$ "§%" §$ !!();`? (6认同)
  • 不是它可以在文件中的任何位置.我将在另一个例子中编辑 (2认同)

Ada*_*ney 7

此前,在PhpSpec ClassGenerator单元测试库中提供使用的一个很好的例子 __halt_compiler(),其PHP类包含一个PHP类代码模板.

他们最近更新以从单独的文件中读取模板,但最初该getTemplate()方法将尝试读取__halt_compiler()调用后的文件中提供的PHP代码模板.这样可以避免<?php令牌被解析.

/**
 * The Class Generator is responsible for generating the classes from a resource
 * in the appropriate folder using the template provided
 */
class ClassGenerator
{
    //...

    /**
     * @return string
     */
    protected function getTemplate()
    {
        return file_get_contents(__FILE__, null, null, __COMPILER_HALT_OFFSET__);
    }
}
__halt_compiler();<?php%namespace_block%

class %name%
{
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*amS 5

这是另一种可能的用途。我有一个很长的 PHP 函数文件。其中许多目前无效,但可能很快就会需要。我想禁用它们,但不想完全删除它们。我希望代码对所有开发人员保持可见,以便他们可以在需要时恢复代码。而且任何通过 grep 搜索的人仍然会找到代码。

所以我将代码移到文件末尾,并想“将其注释掉”。然而,函数本身有注释。所以我需要在原始代码中每个块注释结束后开始一个新的块注释。__halt_compiler(); 在不改变任何其他线路的情况下完成这项工作。

(如果我删除代码并将其提交到版本控制系统,这确实允许我恢复代码,但其他开发人员将看不到它,除非他们是新来的。)

  • “但不要完全删除它们,以防我改变主意”——这就是您使用源代码控制版本的原因。您永远不会注释掉代码 - 您可以删除它们并在必要时恢复。这是一个由糟糕的开发实践造成的糟糕例子。 (4认同)
  • 好吧,我承认我已经简化了我的答案(现在已澄清),因为我觉得问题主要是关于 __halt_compiler 而不是最佳开发实践。您的断言“每个文件都必须处于源代码控制中”和“注释掉代码永远是不对的”可能有点限制性。即使你不这样做,像我这样的其他人也可能在特定情况下这样做。请不要开始一场口水战——我觉得我已经解释了一个有效的用例。 (2认同)