Doc #69811 [Ana->Csd]: Cannot bind closure to scope of internal class stdClass
| From: | cmb@php.net | 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&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