【问题标题】:Understanding PHP declare() and ticks了解 PHP declare() 和刻度
【发布时间】:2015-07-08 05:19:38
【问题描述】:

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

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

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

一个tick是每N个低级tickable发生的事件 解析器在声明块中执行的语句。价值 for N 在声明块的指令中使用 ticks=N 指定 部分。

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

我真正的困惑在于这个声明(来自链接的 so 帖子)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手册的另一部分Function arguments

[编辑 2]
也在Process Control

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

【问题讨论】:

  • @HoboSapiens 我已经看到了 SO 帖子并在问题中提到了它。我有一些我还没有理解的东西
  • 这与您已经链接到的页面上提出的问题基本相同,其中有一些tick 用法的好例子。如果该问题不能回答您的问题,您需要更清楚地了解您不了解的内容。
  • @HoboSapiens 我会尽快为这个问题添加更多细节。
  • @HoboSapiens 我添加了更多细节。希望这能让我更清楚地了解我的疑问。

标签: php control-structure


【解决方案1】:

当 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)register_tick_function() 的帮助下,您现在可以在语句/记号之间执行代码。 register_tick_function 指定在发生滴答事件时应该调用哪个函数。并且声明设置了在滴答事件发生之前应该经过多少滴答。

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

如果您使用declare(ticks=3),那么someFunction() 将在每第三个语句/tick 上执行一次。

例子:

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() 将检查客户端是否仍然连接。

【讨论】:

    【解决方案2】:

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

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

    • 作为declare(encoding=…),用于声明 PHP 文件的编码。 (从这个意义上说,它与&lt;meta charset="…"&gt; 的服务器端版本相当。)

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

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

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

    【讨论】:

    • 我有declare()另一部分php手册Function arguments
    • 这是 PHP 7.0 预期的新功能,尚未发布。我故意只描述当前 PHP 版本中存在的功能。
    【解决方案3】:

    本文未提及的一种用法或可能重复的答案是捕捉信号。

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

    【讨论】:

    • 很抱歉,“你需要”的说法是不正确的。 “你可以,但你真的不应该”是正确的。 Tick 处理程序用于捕获信号非常昂贵(或非常不可预测)。您应该(从很久以前的 php 5.3 起)使用pcntl_signal_dispatch() (manual) 以可预测的方式处理信号。我可以找到很多声称从 5.3 开始甚至不推荐使用蜱的说法,但似乎找不到任何可靠的来源来支持这一点 - 我的个人经验表明 pcntl_signal_dispatch 总是更好。
    • @Mikk3lRo 实际上带有刻度和 pcntl_signal 的示例来自 php 文档中的官方示例部分,请查看 php.net/manual/en/function.pcntl-signal.php 所以我不知道你从哪里得到它应该的信息'不被使用或已弃用
    • @SasaBlagojevic 传真机是存在的,并且有据可查它们是如何工作的。对于非常特定的目的,它们是优越的。但是说您需要使用传真机进行通信是完全不正确的。 Ticks 被弃用确实似乎只不过是一种普遍的误解 - 但如果你真的不知道我从哪里得到这个想法,请使用谷歌 php ticks deprecated... 我坚持我的评论,即 pcntl_signal_dispatch 远远优于刻度处理程序在几乎所有用例中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 2012-05-21
    • 2015-05-13
    • 2022-06-16
    相关资源
    最近更新 更多