Doc #69811 [Ana->Csd]: Cannot bind closure to scope of internal class stdClass

From: Date: Tue, 08 Sep 2015 16:47:01 +0000
Subject: Doc #69811 [Ana->Csd]: Cannot bind closure to scope of internal class stdClass
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-12736@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69811&edit=1 ID: 69811 Updated by: cmb@php.net Reported by: olivier dot laviale at gmail dot com Summary: Cannot bind closure to scope of internal class stdClass -Status: Analyzed +Status: Closed Type: Documentation Problem -Package: Documentation problem +Package: Class/Object related Operating System: Linux PHP Version: 7.0.0alpha1 -Assigned To: +Assigned To: cmb Block user comment: N Private report: N New Comment: This bug has been fixed in the documentation's XML sources. Since the online and downloadable versions of the documentation need some time to get updated, we would like to ask you to be a bit patient. Thank you for the report, and for helping us make our documentation better. Previous Comments: ------------------------------------------------------------------------ [2015-09-08 16:45:49] cmb@php.net Automatic comment from SVN on behalf of cmb Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=337785 Log: Closure::bind() doesn't allow to bind to scope of internal classes anymore (fixes #69811) ------------------------------------------------------------------------ [2015-06-16 22:24:00] kalle@php.net Hi Olivier For the time being, I can only think of the following posibilities to achieve what you are trying to: 1) Simply create your own stdClass object, or use Anonymous Classes (also available in PHP7) 2) Reflection. This is heavy and really should not be used in production code: <?php class Alphabet { public $a, $b, $c; protected $d, $e, $f; private $g, $h, $i; public function __construct() { foreach(range('a', 'i') as $letter) { $this->{$letter} = random_int(0, 10000); } } public function getPublicVars(Alphabet $alphabet) { $ref = new ReflectionObject($alphabet); $props = []; foreach($ref->getProperties(ReflectionProperty::IS_PUBLIC) as $prop) { $props[$prop->name] = $prop->getValue($alphabet); } return($props); } } var_dump(Alphabet::getPublicVars(new Alphabet)); ?> 3) Casting to an array: <?php class Alphabet { public $a, $b, $c; protected $d, $e, $f; private $g, $h, $i; public function __construct() { foreach(range('a', 'i') as $letter) { $this->{$letter} = random_int(0, 10000); } } public function getPublicVars(Alphabet $alphabet) { return(array_filter((array) $alphabet, function($key) { return($key{0} !== "\0"); }, ARRAY_FILTER_USE_KEY)); } } var_dump(Alphabet::getPublicVars(new Alphabet)); ?> This should be considered your last resort (and please do not tell anyone that the code was "promoted" from PHP.net as this is dirty stuff!) I hope this can guide you a little further in the right direction at least :) ------------------------------------------------------------------------ [2015-06-14 21:39:03] olivier dot laviale at gmail dot com Thanks for your reply Kalle. There's indeed an error in my code example, should be as follows: ``` <?php class A { private $a = 1; protected $b = 2; public $c = 3; static public function get_public_vars($object) { $get_public_vars = Closure::bind(function($object) { return get_object_vars($object); }, null, 'stdClass'); return $get_public_vars($object); } } var_dump(A::get_public_vars(new A)); ``` Now that we can't bind stdClass, what's the best way to get *only* the public properties of an object, since get_object_vars() executes from the current scope? ------------------------------------------------------------------------ [2015-06-13 06:25:20] kalle@php.net To clarify Laurence's change; This is intended behaviour that you cannot bind a closure to an class defined internally. Also I think you have a mistake in the example, as you pass a newly created instance of 'A' to the 'A::get_public_vars()' method, but 'A::get_public_vars()' still assumes '$this' in the return statement, not that it would render the practice of binding closures to internally classes anymore allowed ;-) ------------------------------------------------------------------------ [2015-06-12 12:55:13] olivier dot laviale at gmail dot com Description: ------------ Hi, Looks like the following code is no longer possible with PHP7. The following error is raised: "Cannot bind closure to scope of internal class stdClass". I understand that PHP7 may introduce BC changes, but there's no mention about it in the documentation: http://php.net/manual/en/closure.bind.php Test script: --------------- <?php class A { private $a = 1; protected $b = 2; public $c = 3; static public function get_public_vars() { $get_public_vars = Closure::bind(function($object) { return get_object_vars($object); }, null, 'stdClass'); return $get_public_vars($this); } } var_dump(A::get_public_vars(new A)); Expected result: ---------------- [ 'c' => 3 ] Actual result: -------------- Error: Cannot bind closure to scope of internal class stdClass ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=69811&edit=1

« previous php.doc.bugs (#12736) next »