|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2013-08-30 23:55 UTC] 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 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 22:00:01 2025 UTC |
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.*I'm not sure about the following behaviour: <?php class A { public static function exec(callable $c) { // this works $c(); // this won't return call_user_func($c); } public static function doSomething() { // implicit static in 5.x, non-static in 7 return self::exec(function(){ return "okay"; }); } } echo A::doSomething(); After this commit, the closure created by doSomething and passed to exec() cannot be called by call_user_func anymore: "Fatal error: Non-static method A::{closure}() cannot be called statically in staticClosures.php on line 10" However, calling $c(); still works. Is this expected or an unwanted effect of this patch?