-
Notifications
You must be signed in to change notification settings - Fork 7.9k
loosen the restrictions on ReflectionClass::newInstanceWithoutConstructor() #733
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
Conversation
+1 |
@Tyrael could tests for:
be added to this suite? |
Also, I'll need to compile this and try it against |
👍 |
Shouldn't we disallow as well classes with a non public constructor() ? Should they be intern or user. Someone putting a non public constructor want to take hand over its objects creation (singletons for example), so I guess it would be better also to disallow newInstanceWithoutConstructor() in such a case |
@jpauli I don't think that we should: |
Yup last argument I forgot about is enough to me :-) |
This patch seems to work for me (as of Ocramius/Instantiator#8). The only thing missing now is finding out when it doesn't or shouldn't work. If I get this correctly, I this should give me the classes that are not yet supported by <?php
$instantiable = function($className) use (& $instantiable) {
if (! $className) {
return true;
}
$reflection = new ReflectionClass($className);
$hasFinalConstruct = false;
if ($reflection->hasMethod('__construct')) {
$hasFinalConstruct = $reflection->getMethod('__construct')->isFinal();
}
$parentClass = $reflection->getParentClass();
return $instantiable($parentClass ? $parentClass->getName() : null)
&& ! ($reflection->isInternal() && $hasFinalConstruct);
};
$negate = function ($function) {
return function (...$args) use ($function) {
return ! $function(...$args);
};
};
var_dump([
'instantiable' => array_filter(get_declared_classes(), $instantiable),
'not_instantiable' => array_filter(get_declared_classes(), $negate($instantiable)),
]); Here's an example output: http://3v4l.org/rAOrK @Tyrael does this make any sense? EDIT: was excluding abstract classes, my bad... |
@Ocramius Final classes are disallowed, not final constructors. The error message in the patch should also be updated to reflect that. |
Yeah, figured that, probably edited that comment of mine a dozen times by now :-) |
@nikic @Ocramius hm, you just made me realize that we have classes with final final constructors where the class itself isn't final. @Ocramius is there a reason to check so many things via Reflection in Instantiator instead of "always" trying to use Reflection to instantiate the class first, and catch the ReflectionException and do the dirty hacks there? In 5.6 most classes will be instantiated through Reflection, so the checks there just wasted cpu and memory cycles. |
@Tyrael Is there any class apart from SimpleXMLElement that does that? |
Yeah, fatals fatals fatals everywhere, plus previous php versions, plus the bogous 5.4.29 and 5.5.13. Checks are cached anyway. |
@nikic from a quick look only SimpleXMLElement and Transliterator does this. |
… instantiate every class except those internal classes with a final __construct()
I've updated the exception message to better match the actual check. |
That was quick! |
yeah, I've really want to have an RC3 out this week, we can still tweak on the change if something comes up. |
…tructor in UPGRADING see the discussion on the mailing list and in the pull request for details: #733
* PHP-5.6: mention the changes regarding ReflectionClass::newInstanceWithoutConstructor in UPGRADING see the discussion on the mailing list and in the pull request for details: #733
…tructor in UPGRADING see the discussion on the mailing list and in the pull request for details: #733
allow instantiating any class except internal classes with a final __construct().
see http://www.serverphorums.com/read.php?7,959450,987654#msg-987654 (and the whole thread) for the full discussion, but basically with the removal of the unserialize O: trick which allowed the instantiation of internal classes with a custom serializer there is no way to do that from the userland, and that breaks a bunch of libs/apps out there.
the original restriction was in place, because there are internal classes with custom object storage, where the object initialization happens in the __construct instead of the create_object hook, but for non final constructors it is already a problem which can occur (a class which has it's own __construct method which doesn't call parent::__construct() extending an internal class), so it is ok to allow the same problems surfacing here also.