理解 PHP declare() 和 ticks

Understanding PHP declare() and ticks

今天我在浏览 php 手册时偶然发现了一个控制结构 declare

The declare construct is used to set execution directives for a block of code

这就是 declare 应该做的。老实说我没看懂。再次阅读它发现了一个新事物 Ticks

A tick is an event that occurs for every N low-level tickable statements executed by the parser within the declare block. The value for N is specified using ticks=N within the declare block's directive section.

我也没看懂。 N low-level tickable statements 是什么意思,要是有好的样例代码就好理解了。但是在手册中找到了none。在SOQ1上找到了一些,反而增加了我的好奇心和疑惑。任何人都可以知道这是做什么用的,我们可以在哪里使用它。

我真正的困惑是这个声明(来自链接所以post)you can declare a tick-function which checks each n executions of your script whether the connection is still alive or not。因此,当我在 php 文件上注册一个 tick = 20 的 tick 函数并执行它时,该文件将一直存在直到 20 执行完成(当它被错误地认为是多线程时得到这个想法)。这是我的想法,我认为它不正确..

或者它是 while($x = 20)

的简单替代品

[编辑 1]
我还看到 declare() php 手册的另一部分 Function arguments

的实施

[编辑 2]
也在 Process Control

You use the declare() statement to specify the locations in your program where callbacks are allowed to occur. This allows you to minimize the overhead of handling asynchronous events

实际上:忽略 declare() 指令。除非你 运行 进入使用它的代码——这种情况非常罕见——否则你可以安全地忘记它曾经存在过。

话虽这么说,这里是详细信息。 declare() 指令目前用于两个完全不相关的事情:

  • As declare(encoding=…),用于声明 PHP 文件的编码。 (从这个意义上说,它相当于 <meta charset="…"> 的服务器端版本。)

    但是不要使用这个。在大多数情况下,脚本编码无关紧要。如果有机会,PHP 编码应该通过 zend.script_encoding 配置值全局设置(希望为 "UTF-8")。在文件级别设置它是令人困惑和不必要的。

  • As declare(ticks=…),用于定义调用 tick 函数的频率。 Tick 函数由 PHP 解释器定期调用,并使用 register_tick_function.

    设置

    虽然 php.net 上的一些评论建议使用它来实现网络访问超时,但实际上并没有按预期工作,因为当解释器在本机函数调用中被阻塞时,不会触发滴答.它可能在基准测试中有一些应用,但除此之外它基本上没用。我会避免它。

此处未提及的一种用法或可能重复的答案是捕获信号。

如果你有一个 CLI 脚本并且想要捕获用户信号(比如 SIGHUP 或 SIGTERM (CTRL+C)),你需要 declare(ticks...pcntl_signal https://secure.php.net/manual/en/function.pcntl-signal.php 允许你捕捉这些信号(与 shell 脚本中的陷阱相同)

当PHP执行你的脚本时,执行可以看做是执行了很多语句。大多数语句都会导致 Tick,但不一定所有语句都会这样做。 (手册说:Typically, condition expressions and argument expressions are not tickable.

这个块通常会导致 5 个滴答声,因为您正在执行 5 个语句:

$a = 1;
$B = 2;
$a = 3;
$B = 4;
$a = 5;

而这个块通常会导致 5 个滴答声,而当 while 循环结束时再多一个滴答声也算作 statement/tick:

while ($i < 5)
    $a++;

declare(ticks=N)register_tick_function() 的帮助下,您现在可以在 statements/ticks 之间执行代码。 register_tick_function 指定当 tick 事件发生时应调用哪个函数。并声明设置在 tick 事件发生之前应该经过多少个 tick。

使用 declare(ticks=1)register_tick_function('someFunction'); 您将在每个 statement/tick.

之间调用 someFunction() 代码

如果您使用declare(ticks=3),那么someFunction()将在每三分之一statement/tick执行。

示例:

function handler(){
    echo "x";
}
register_tick_function("handler");
$i = 0;
declare(ticks = 4) {
    while ($i < 9)
        echo ++$i;
}

此脚本将输出:1234x5678x9 就是这么简单。

"whether the connection is still alive" 的链接问题本身并不有趣,实际上与上述问题无关。这只是您可以在每个滴答事件中做的事情。但你也可以做一些完全不同的事情。提到的只是一些脚本可能需要相当长的时间才能执行,并且在执行期间,客户端可能会断开连接。 (想象关闭浏览器,而脚本仍在 运行ning。)PHP 默认情况下将继续 运行 脚本,即使客户端已断开连接。您可以使用函数 connection_aborted() 来检测客户端是否已断开连接。这是你也可以在根本不使用刻度的情况下做的事情。

现在假设您希望脚本在客户端断开连接后立即停止 运行ning。只需使用 ...

function killme() {
    if (connection_aborted()) {
        die();
    }
}
register_tick_function('killme');
declare(ticks=1);

... 并且您的脚本将在每个代码语句之后调用 killme()killme() 将检查客户端是否仍处于连接状态,如果未连接则 die()