php / php/doc-en

Clarify magic methods aren't called recursively in any function called within the magic method

Open
#2,669 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug Category: Engine QA
Dominant language
XML
Stars
596
Forks
890
Avg merge
1d 15h
Merged PRs (30d)
55

Description

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() will return null and raise an E_WARNING if there is no foo property defined, rather than calling __get() a second time. However, overload methods may invoke other overload methods implicitly (such as __set() triggering __get()).

The following code:

<?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

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked PHP manual section on object overloading, especially the __get() and __set() notes, and reproduce the provided PHP 8.2.6 example. Confirm how a magic method already present in the call stack affects nested property access, then update the note so the documented limitation matches the observed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.