Bug #72194 [Opn]: unset() on declared class properties undeclares it partially
| From: | bwoebi@php.net | Date: | Sun, 15 May 2016 14:46:40 +0000 |
| Subject: | Bug #72194 [Opn]: unset() on declared class properties undeclares it partially | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-201104@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72194&edit=1
ID: 72194
Updated by: bwoebi@php.net
Reported by: pierre dot rineau at makina-corpus dot com
Summary: unset() on declared class properties undeclares it
partially
Status: Open
Type: Bug
Package: Reflection related
Operating System: Any
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
The property (as in property declaration) still exists. Only dynamic properties can completely
vanish.
The correct construct checking for existence of the property *value* is isset().
Note that unset() sets the value to undefined [not null!], but does not affect the existence of the
property declaration if it is a declared one.
class A { public $b; }
$a = new A;
var_dump(property_exists($a, "b")); // true
var_dump(isset($a->b)); // false (as $a->b is null)
var_dump($a->b); // null
var_dump(property_exists($a, "c")); // false
$a->c = 1;
var_dump(property_exists($a, "c")); // true
unset($a->c);
var_dump(property_exists($a, "c")); // false
unset($a->b);
var_dump(property_exists($a, "b")); // true
var_dump(isset($a->b)); // false (as $a->b is undefined)
var_dump($a->b); // null and emits a notice ($a->b is undefined)
It's true that you can trick code using it (wrongly); that code probably should be using
isset(). property_exists() is really only meant to check the existence of declaration or it actually
having a value.
Previous Comments:
------------------------------------------------------------------------
[2016-05-12 13:19:29] pierre dot rineau at makina-corpus dot com
Yes, it is either one of:
- property_exists() should not return true for unset() properties
- unset() un-declares statically declared class properties
------------------------------------------------------------------------
[2016-05-11 13:58:06] nikic@php.net
To clarify, the "bug" you are reporting here is that property_exists() returns true for
properties that have been unset?
------------------------------------------------------------------------
[2016-05-11 11:16:03] pierre dot rineau at makina-corpus dot com
https://3v4l.org/3sAs5
------------------------------------------------------------------------
[2016-05-11 11:12:50] pierre dot rineau at makina-corpus dot com
Changed title.
------------------------------------------------------------------------
[2016-05-11 11:11:47] pierre dot rineau at makina-corpus dot com
Description:
------------
If you declare a class with declared properties, you might want to use unset() to reset the property
value to null, but when accessing it later, it causes a "undefined property" warning.
This seems legit, but it becomes tricky once you notice that property_exists() returns true before
calling unset(), which is the wanted behavior since the property is declared (even when
uninitialized), but it also returns true after calling unset(), which is incompatible with the
"undefined property" warning.
It seems to always have worked this way, but any code using property_exists() will be tricked by the
false positive.
[someuser@localhost] ~/current
> php -v
PHP 5.5.25 (cli) (built: May 14 2015 10:02:12)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies
with Xdebug v2.4.0RC2, Copyright (c) 2002-2015, by Derick Rethans
[someuser@localhost] ~/current
> php -a
Interactive shell
php > class A { public $b; };
php > $a = new A;
php > echo property_exists($a, 'b');
1
php > $a->b;
php > unset($a->b);
php > echo property_exists($a, 'b');
1
php > $a->b;
PHP Notice: Undefined property: A::$b in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
php >
pounard@guinevere] ~
> php -v
PHP 7.0.6 (cli) (built: May 1 2016 07:39:38) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans
[pounard@guinevere] ~
> php -a
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php/modules/redis.so'
- /usr/lib/php/modules/redis.so: undefined symbol: zval_used_for_init in Unknown on line 0
Interactive shell
php > class A { public $b; };
php > $a = new A;
php > echo property_exists($a, 'b');
1
php > $a->b;
php > unset($a->b);
php > echo property_exists($a, 'b');
1
php > $a->b;
PHP Notice: Undefined property: A::$b in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
php >
Test script:
---------------
class A { public $b; };
$a = new A;
echo property_exists($a, 'b'); // Returns '1'
$a->b; // Remains silent
unset($a->b);
echo property_exists($a, 'b'); // Still returns '1'
$a->b; // Cause a "Notice: Undefined property A::$b"
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72194&edit=1