[php-src] Issue #11920: Unable to recursivelly call __set()
| From: | survik1 | Date: | Wed, 09 Aug 2023 11:15:35 +0000 |
| Subject: | [php-src] Issue #11920: Unable to recursivelly call __set() | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-245139@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/11920
Author: survik1
### Description
Hello, we are upgrading our old and huge application to PHP 8.2 and we started to get
Creation
of dynamic property is deprecated error which really surprised us as we have related classes
fully covered with __set and __get methods.
Upon further investigation we found out that __set method is not being called for same $name if this
method was found within stack. There is this note in php doc that could be related, but it just
mention calling from within the same method, not having the call in stack. If this is a desired
behavior, I believe that doc should be updated to inform that this structure is not possible.
```
PHP will not call an overloaded method from within the same overloaded method. That means, for
example, writing return $this->foo inside of
[__get()](https://www.php.net/manual/en/language.oop5.overloading.php#object.get) will return null
and raise an E_WARNING if there is no foo property defined, rather than calling
[__get()](https://www.php.net/manual/en/language.oop5.overloading.php#object.get) a second time.
However, overload methods may invoke other overload methods implicitly (such as
[__set()](https://www.php.net/manual/en/language.oop5.overloading.php#object.set) triggering
[__get()](https://www.php.net/manual/en/language.oop5.overloading.php#object.get)).
```
The following code:
```php
<?php
class test {
protected $data = [];
public function set_status($value) {
if ($value === 1) {
$this->storage = 'a';
}
$this->data['status'] = $value;
}
public function set_storage($value) {
if ($value === 'a') {
$this->status = 2;
}
$this->data['storage'] = $value;
}
public function __set($name, $value) {
if (method_exists($this, 'set_' . $name)) {
$this->{"set_{$name}"}($value);
}
}
public function getStatus() {
return $this->data['status'];
}
}
$c = new test();
$c->status = 3;
echo $c->getStatus() . ":" . @$c->status . PHP_EOL;
$c->status = 1;
echo $c->getStatus() . ":" . @$c->status . PHP_EOL;
```
Resulted in this output:
```
3:
1:2
```
But I expected this output instead:
```
3:
2:
```
### PHP Version
PHP 8.2.6
### Operating System
Ubuntu 22.04