Edit report at https://bugs.php.net/bug.php?id=65598&edit=1

 ID:                 65598
 Comment by:         bixuehujin at gmail dot com
 Reported by:        php at davidstockton dot com
 Summary:            Closure executed via static autoload incorrectly
                     marked as static
 Status:             Open
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   Centos 6
 PHP Version:        5.5.3
 Block user comment: N
 Private report:     N

 New Comment:

Indeed,it is odd and out of expect.

AFAIK, there is no difference between create closure in static methods and 
require a file that will create a closure. Because of the created closure in 
both have the same scope.
 
Consider the following two examples:

1: create closure in static method

//main.php

class Test {
    public static function createClosure() {
        $c = function () {
            //some code
        };
        return $c;
    }
}

2: create closure in a single file and require it

//main.php

class Test {
    public static function createClosure() {
        require 'closure.php';
        return $c;
    }
}

//closure.php
$c = function () {
    //some code
};

The both examples have the same behavior, and both scope of $c are Test. 

But according to the invariants in Zend/zend_closures.c, say:

> If the closure is unscoped, it has no bound object.
> The the closure is scoped, it's either static or it's bound 
> see detail: 
> https://github.com/php/php-src/blob/47ee470992014c738891d05b5acc89c2de90f2ac/Zend/zend_closures.c#L483,L498

So the behavior of this issue is valid according to the invariants.


*By the way, i am also want to know why we should have the invariants.*


Previous Comments:
------------------------------------------------------------------------
[2013-09-17 21:30:38] php at davidstockton dot com

The closure is not created in a static method, it's just loaded via an 
autoloader 
that happens to be static. Seems odd that we should expect different behavior 
of the 
code based on if the autoloader is static or non-static.

------------------------------------------------------------------------
[2013-09-17 20:52:18] bixuehujin at gmail dot com

The reason is closures created in static methods are static, even without the 
keyword.

see 
https://github.com/php/php-src/blob/a447acdcc6f12ea3a5dcd22416cb033e62995935/Zend/tests/closure_045.phpt

------------------------------------------------------------------------
[2013-08-30 23:55:29] php at davidstockton dot com

Description:
------------
If I load a class via a static autoloader which has executable code (including 
a 
closure) and then try to bind the closure to an object of the class, I get a 
warning and error:

Warning: Cannot bind an instance to a static closure
and
Fatal error: Using $this when not in object context

If I run the script directly (not via autoloader) everything works as expected.

If I make the autoloader non-static, everything works as expected.

Test script:
---------------
Sample contains two files, a static autoloader which will load the class file 
and the class file which also contains executable code.

If the autoloader is a plain function or a non-static method then the code 
works as expected. If the executable code is removed from the class file and 
placed into the autoloader file, everything works as expected.

php Autoloader.php (bad behavior)
php ClosureBug.php (correct behavior)

https://gist.github.com/dstockto/6395158



Expected result:
----------------
42

Actual result:
--------------
Warning: Cannot bind an instance to a static closure in 
/vagrant/src/Bug/ClosureBug.php on line 9

Fatal error: Using $this when not in object context in 
/vagrant/src/Bug/ClosureBug.php on line 19


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=65598&edit=1

Reply via email to