Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 7.0: Returning by reference from magic methods, e.g. __call(), __callStatic() #1675

Open
MarkMaldaba opened this issue Feb 6, 2024 · 4 comments

Comments

@MarkMaldaba
Copy link
Contributor

I've just come across an interesting thing that I can't find any documentation for, but which is a clear difference in implementation between PHP versions.

It appears that the magic methods (e.g. __call(), __callStatic(), etc.) allow you to return values by reference as of PHP 7. However, this doesn't work in PHP 5.

Example (3v4l.org)

PHPCompatibility should warn if magic methods are prefixed by & when testing against PHP < 7.0.

@jrfnl
Copy link
Member

jrfnl commented Feb 6, 2024

@MarkMaldaba I agree there is a change (which may or may not be detected in PHPCompatibility, I need to check), but the change has nothing to do with __call() or __callStatic() as far as I can see: https://3v4l.org/gcUhi

@MarkMaldaba
Copy link
Contributor Author

MarkMaldaba commented Feb 8, 2024

Hi @jrfnl. No, your fiddle is not doing the same thing and I would expect things to work the same across PHP versions if you are not returning by reference.

The point is that PHP < 7 does not allow you to return values by reference from __call() and __callStatic() therefore attempting to assign their value to a variable, by reference, will trigger the strict standards warning (or simply fail without an error) on earlier versions. This is because you are returning an unbound value from the function and therefore there is no reference to assign.

However, once the ability to return by reference was added, the assign by reference is acceptable and (a) no longer throws a notice; and (b) correctly holds a reference to the static class property, meaning changes made to the variable in the outer scope affect the class variable in the inner scope. It is the second of these that is the more significant backwards-compatibility issue, and the reason I am flagging this.

Here is another fiddle which demonstrates the difference between function __call() and function &__call() within the same PHP version: https://3v4l.org/3UWMV

@jrfnl
Copy link
Member

jrfnl commented Feb 9, 2024

@MarkMaldaba It would be helpful to find the exact change in PHP, either the commit which made this change or any RFC/UPGRADING reference related to it.

I want to properly understand what was exactly has changed to be able to evaluate whether this is sniffable or not and what exactly should be sniffed for.

@MarkMaldaba
Copy link
Contributor Author

I'm not completely sure, but this looks like the commit where it was changed: php/php-src@5e8133f

This is a change to how __call() and __callstatic() were implemented that was made in PHP 7.0. I'm wondering if this was a byproduct of the change, rather than an intended outcome.

@jrfnl jrfnl changed the title Returning by reference from magic methods, e.g. __call(), __callStatic() PHP 7.0: Returning by reference from magic methods, e.g. __call(), __callStatic() Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants