30

今天我在翻阅 php 手册,偶然发现了一个控制结构声明

声明构造用于设置代码块的执行指令

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

滴答是在声明块中由解析器执行的每 N 个低级可滴答语句发生的事件。N 的值是在声明块的指令部分中使用 ticks=N 指定的。

我也不明白。这是什么意思N low-level tickable statements如果有一个好的示例代码,那么它就会很容易理解。但是在手册中没有找到。我在 SO Q1上找到了一些,这实际上增加了我的好奇心和困惑。那么任何人都可以这样做,我们可以在哪里使用它。

我真正的困惑是这个声明(来自链接的so 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 的刻度函数并执行它时,该文件将一直存在,直到 20 执行完成(当它被错误地认为是多线程时得到了这个想法)。这是我的想法,我认为它不正确..

或者它是一个简单的替代品while($x = 20)

[编辑 1]
我还看到了declare()另一部分 php 手册函数参数的实现

[编辑 2]
也在过程控制中

您可以使用 declare() 语句来指定程序中允许发生回调的位置。这使您可以最大程度地减少处理异步事件的开销

4

3 回答 3

28

当 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 循环结束时再增加一个滴答声也算作一个语句/滴答声:

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

借助declare(ticks=N)and register_tick_function(),您现在可以在语句/记号之间执行代码。register_tick_function 指定在发生滴答事件时应该调用哪个函数。并且声明设置了在滴答事件发生之前应该经过多少滴答。

使用declare(ticks=1)并且register_tick_function('someFunction');您将someFunction()在每个语句/刻度之间调用代码。

如果您使用declare(ticks=3), thensomeFunction()将在每第三个语句/滴答声中执行一次。

例子:

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

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

现在,与“连接是否仍然存在”相关的问题中的含义本身并不是很有趣,并且实际上与上述内容无关。这只是你可以在每个滴答事件上做的事情。但你也可以做一些完全不同的事情。所提到的只是一些脚本可能需要相当长的时间才能执行,并且在执行期间,客户端可以断开连接。(想象一下关闭浏览器,而脚本仍在运行。)默认情况下,PHP 将继续运行脚本,即使客户端已断开连接。您可以使用该功能connection_aborted()来检测客户端是否已断开连接。这也是你完全不用刻度也可以做到的事情。

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

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

...并且您的脚本将killme()在您的代码的每个语句之后调用。killme()将检查客户端是否仍然连接以及die()何时不连接。

于 2015-07-14T11:03:55.697 回答
10

在实践中:忽略declare()指令。除非您遇到使用它的代码(这种情况非常罕见),否则您可以放心地忘记它曾经存在过。

话虽如此,这是细节。该declare()指令目前用于两个完全不相关的事情:

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

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

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

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

于 2015-07-08T06:21:02.550 回答
4

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

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

于 2015-07-08T06:58:34.743 回答