Understanding PHP declare() and ticks
Asked Answered
E

4

33

Today I was looking through the php manual and stumbled upon a control structure declare.

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

This is what declare is supposed to do. To be honest I didn't understood it. On reading again it found a new thing 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.

I didn't understand it either. what does it mean by N low-level tickable statements If there had been a good sample code, then it would have been easy to understand. But none was found in the manual. I have found some on SO Q1, which actually increased my curiosity and confusion. So can anyone what is this for and where can we use this.

My actual confusion is with this statement (from the linked so post) you can declare a tick-function which checks each n executions of your script whether the connection is still alive or not. So when I register a tick function with tick = 20 on a php file and execute it, the file will be alive till 20 execution is complete(got this idea when it was wrongly considered as multithreaded). This is the idea i have got, I dont think its correct..

Or is it a simple replacement for while($x = 20)

[EDIT 1]
I have also seen the implementation of declare() another section of php manual Function arguments

[EDIT 2]
Also in 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

Eclogue answered 8/7, 2015 at 5:19 Comment(5)
possible duplicate of What are ticks used for in PHP?Tuesday
@HoboSapiens I have seen that SO post and have mentioned it in the question. I have something that I still haven't understoodEclogue
This is essentially the same question as was asked on the page you have already linked to where there are some good examples of tick usage. If that question doesn't answer your questions you'll need to be clearer about what you don't understand.Tuesday
@HoboSapiens I will add more details to the question soon.Eclogue
@HoboSapiens I have added more details. Hope this will give more clear idea on my doubt.Eclogue
D
34

When PHP is executing your script, the execution can be seen as a lot of statements being executed. Most statements cause a Tick, though not necessarily all statements do so. (Manual says: Typically, condition expressions and argument expressions are not tickable.)

This block would normally cause 5 ticks, as you are executing 5 statements:

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

And this block would normally cause 5 ticks, and one more tick as the end of the while loop also is counted as a statement/tick:

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

With the help of declare(ticks=N) and register_tick_function(), you can now execute code in between the statements/ticks. The register_tick_function specifies which function should be called when a tick event occurs. And the declare sets how many tick should pass, before a tick event occurs.

With declare(ticks=1) and register_tick_function('someFunction'); you will call someFunction() code in between every statement/tick.

If you use declare(ticks=3), then someFunction() will be executed on every third statement/tick.

Example:

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

This script will output: 1234x5678x9 It's that simple.

Now what is meant in the linked question with "whether the connection is still alive", is not really interesting on itself and is not actually related to the above mentioned. It is just something you COULD do on every tick event. But you can also do something totally different. What is mentioned is simply that some scripts can take quite some time to execute and that during the execution, the client can disconnect. (Imagine closing the browser, while the script is still running.) PHP will by default continue to run the script, even if the client has disconnected. You can use the function connection_aborted() to detect if the client has disconnected. This is something you COULD also do without using ticks at all.

Now let's say for example that you want your script to stop running as soon as the client disconnects. Simply use ...

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

... and your script will call killme() after each statement of your code. killme() will check if the client is still connected and die() when it isn't.

Dread answered 14/7, 2015 at 11:3 Comment(0)
C
10

In practice: Ignore the declare() directive. Unless you run into code that makes use of it — which is very rare — you can safely forget that it ever existed.

That being said, here's the details. The declare() directive is currently used for two completely unrelated things:

  • As declare(encoding=…), for declaring the encoding of a PHP file. (In this sense, it's comparable to a server-side version of <meta charset="…">.)

    But don't use this. Under most circumstances, the script encoding doesn't matter. If by some chance it does, the PHP encoding should be set globally (hopefully to "UTF-8") by the zend.script_encoding configuration value. Setting it at the file level is confusing and unnecessary.

  • As declare(ticks=…), for defining the frequency at which tick functions are called. Tick functions are called periodically by the PHP interpreter, and are set up using register_tick_function.

    While some of the comments on php.net suggest using it to implement timeouts on network accesses, that doesn't actually work as expected, as ticks are not fired while the interpreter is blocked in a native function call. It might have some applications in benchmarking, but outside of that it's basically useless. I'd avoid it.

Chloric answered 8/7, 2015 at 6:21 Comment(2)
I have declare() another section of php manual Function argumentsEclogue
That's a new feature expected for PHP 7.0, which hasn't been released yet. I'm intentionally only describing features which exist now in current versions of PHP.Chloric
L
4

The one usage not mentioned in this or the possible duplicate answer is catching signals.

If you have a CLI script and want to catch user signals (like SIGHUP or SIGTERM (CTRL+C)), you need declare(ticks... together with pcntl_signal https://secure.php.net/manual/en/function.pcntl-signal.php which allows you to catch those signals (same like trap in shell scripts)

Larghetto answered 8/7, 2015 at 6:58 Comment(3)
Sorry to say, but the statement "you need" is incorrect. "you could, but you really shouldn't" would be correct. Tick handlers are extremely expensive (or very unpredictable) for catching signals. You should (as of php 5.3 aka a long time ago) use pcntl_signal_dispatch() (manual) to handle signals in a predictable manner. I can find a lot of claims that ticks are even deprecated as of 5.3, but can't seem to find any reliable sources to sustain this - my personal experience says pcntl_signal_dispatch is always better though.Calefaction
@Calefaction actually the example with ticks and pcntl_signal is from the official example section in the php docs, take a look php.net/manual/en/function.pcntl-signal.php so I don't know where you got that info that it shouldn't be used or that it is deprecatedSeedbed
@SasaBlagojevic Fax machines exist, and it is well documented how they work. For very specific purposes they are superior. But stating that you need to use a fax machine to communicate is simply incorrect. Ticks being deprecated does indeed seem to be nothing more than a widespread misunderstanding - but google php ticks deprecated if you really don't know where I got the idea... I stand by my comment that pcntl_signal_dispatch is far superior to tick handlers in almost all use cases.Calefaction
V
0

On newer versions of PHP, in most cases declare(ticks=1); can be replaced by:

pcntl_async_signals(true);
Vedette answered 31/1 at 3:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.