Use Static Closures or Closures in PHP?

Asked

Viewed 180 times

5

As of PHP 5.4, the Closures (Or funções anônimas), when declared within the context of a class method (other than static methods), automatically inherit to "within" the $this as a reference to the class containing it.

Example:

class StackOverflow
{
    protected $array = ['stack', 'overflow', 'portugues'];

    public function testClosure($string)
    {      
        $callback = function()
        {
            print_r($this);

            /*
                StackOverflow Object
                (
                    [array:protected] => Array
                        (
                            [0] => stack
                            [1] => overflow
                            [2] => portugues
                        )
                )
            */

            return 'stack';
        };

        return preg_replace_callback('/stick/', $callback, $string);
    }
}

(new StackOverflow)->testClosure('stick overflow');

As seen in the example, when we do the print_r($this), return the current instance of the class StackOverflow.

However, if we made a small change and added the keyword static before the anonymous function declaration, the variable $this does not "matter" the class instance StackOverflow inside:

public function testClosure($string)
{
      // Closure static não importa o $this para o Escopo
      $callback = static function()
      {
          print_r($this); // Undefined variable: this
          return 'stack';
      };

      return preg_replace_callback('/stick/', $callback, $string);
}

As seen in the example, I am using the function preg_replace_callback to be able to make changes in a string through a regex. I mean, I don’t need to have the $this properly within the class, but I only want to use the Closure as a callback.

My question is this::

  1. Since I will not use anything from the context of the current instance of class, we could say that it is more performatic to use the static Closure?

  2. Or the question of $this be "imported" into the scope does not mean loss of performance (since $this of Closure does not receive a copy, but only creates the reference of the same instance of the class currently invoked)?

  • Just to point out, I’ve never heard of Closure could be declared as static (I discovered the short time and I discovered these differences giving print_r) !But again, as @bigown says, the PHP manual is failing its users

2 answers

2


I am surprised that in one of these situations it is possible to access the $this. A static function should never be able to do this. But again, we know how language developers don’t think at all. They knew that this should not be accepted but did not realize that it was possible to bypass by placing the static function inside a non-static function.

If it’s not something documented I’d be afraid to use it. Just because it works doesn’t mean it’s right. There is no guarantee that it will work in the future if it is not documented. Someone will surely say that whoever wears something undocumented deserves what will happen to him in the future if it stops working.

So my official answer is don’t use.

To tell you the truth I don’t know if this what you’re doing makes any sense. Maybe because of lack of context it’s not easy to understand. Maybe it’s me.

Performance is certainly not relevant if you chose PHP. It is not a language that has this quality. The difference of doing something static or per instance will be at the very least. Maybe none.

I would ask if you need to put this in a class. I just don’t do it because I don’t fully understand the problem.

Under normal conditions I would say that a regular function that accesses nothing of the instance should be declared static, even to make it clear that this is the intention. Showing in code what you want is more important than performance. Performance should be considered only if you have measured and seen that it is not meeting needs. Note that I am not talking about closure here, since closure static is not documented according to the AP comment in the question.

If the documentation says you can use a closure static gets the impasse whether or not it should use. Unfortunately these questions could only be asked by those who have authority, the language developers. Even so I would only use it if they put it in the documentation.

  • as a curiosity: recently made use of closure in a function for data filter and access to $this was allowed in version 5.4 of PHP to "upei" the files for the site that was in version 5.3 and did not allow access to $this inside the closure. I found tin.

  • I think I gave you the wrong information on the question, mustache!

  • @Wallacemaxters fix it then.

  • @Johnidouglasmarangon functionality is available from version 5.4 >=

1

According to the PHP documentation, the purposes that could be applied using static in a Closure would be:

  • Prevent it from being linked to the context (Class) in which it is called.

Example:

class Foo
{
    function __construct()
    {
        $func = static function() {
            var_dump($this);
        };
        $func();
    }
};
new Foo();

The exit would be:

Notice: Undefined variable: this in %s on line %d

  • Prevent the binding of $this of Closure to an object by calling the method bindTo (and probably Closure::bind and Closure::call).

    $func = static function() {
        // function body
    };
    
    $func = $func->bindTo(new StdClass);
    
    $func();
    

Would be generated a E_WARNING:

Warning: Cannot bind an instance to a Static closure in /in/sLLS9 on line 5

Other than that, there is nothing but detail documentation, as per exmeplo, whether this implies performance gain or not,.

  • Is this documentation link correct? Is it intended to show the question links? Or is this link specifically http://php.net/manual/en/functions.anonymous.php#functions.Anonymous-functions.Static ?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.