Doc #69811 [Ana]: Cannot bind closure to scope of internal class stdClass
| From: | kalle@php.net | Date: | Tue, 16 Jun 2015 22:24:00 +0000 |
| Subject: | Doc #69811 [Ana]: Cannot bind closure to scope of internal class stdClass | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-12444@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: kalle@php.net
Reported by: olivier dot laviale at gmail dot com
Summary: Cannot bind closure to scope of internal class
stdClass
Status: Analyzed
Type: Documentation Problem
Package: Documentation problem
Operating System: Linux
PHP Version: 7.0.0alpha1
Block user comment: N
Private report: N
New Comment:
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 :)
Previous Comments:
------------------------------------------------------------------------
[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