go to bug id or search bugs for
While working on making Symfony compatible with PHP 8, we're noticing a lot of failure that look like:
TypeError: method_exists(): Argument #1 ($object_or_class) must be of type object|string, XXX given
See e.g. https://travis-ci.org/github/symfony/symfony/jobs/690567745
Can we relax method_exists() and make it accept any value as 1st arg?
None of the changes needed to remove these errors look valuable.
This would lower the cost of migrating to PHP 8 for the community at large.
(Symfony is just an early adopter here.)
Thanks for considering!
Add a Patch
Add a Pull Request
This change was originally made to align the behavior of method_exists() and proprety_exists(), where the latter already only accepted an object|string argument.
However, I have found this change to have an additional benefit after the fact: The issue is that method_exists() also accepts a string as first argument, and will treat it as a class name in that case, which involves invoking the autoloader. This means that if you have code like method_exists($arbitraryValue, 'method') you must make sure that at least !is_string($arbitraryValue) holds beforehand -- at which point you might as well just test for is_object($arbitraryValue). See https://github.com/guzzle/promises/pull/105/files for an instance of such a bug going unnoticed for a long time. This is a pretty severe issue (those autoloader invocations are definitely going to hurt performance, but may also impact security), but the previous behavior of the function made it very easy to make it, because it made it look like passing an arbitrary value to method_exists() is safe.
Now, looking at the particular warning in that travis log, I see that it is guarded by "!is_scalar($default) && !method_exists($default, '__toString')" and as such would not run into this issue. There's definitely false positives. But overall I still think that the tradeoff here is reasonable.
Thanks for the heads up.
For reference, here is the PR to fix the related failures in Symfony:
Let's close then.
> Let's close then.