Req #67422 [Com]: Cannot determine whether newInstanceWithoutConstructor can be used
| From: | tom at r dot je | Date: | Thu, 12 Jun 2014 09:32:50 +0000 |
| Subject: | Req #67422 [Com]: Cannot determine whether newInstanceWithoutConstructor can be used | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-186158@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=67422&edit=1
ID: 67422
Comment by: tom at r dot je
Reported by: tom at r dot je
Summary: Cannot determine whether
newInstanceWithoutConstructor can be used
Status: Open
Type: Feature/Change Request
Package: Reflection related
PHP Version: 5.5.13
Block user comment: N
Private report: N
New Comment:
Looking at how other situations are handled, I wonder why there is a restriction on internal classes
at all.
Given this:
<?php
class MyException extends Exception {
public function __construct() {
}
}
new MyException();
?>
Runs correctly and Exception::__construct() is never called because it's been overridden I see
no reason why newInstanceWithoutConstructor() cannot be used on internal classes.
Previous Comments:
------------------------------------------------------------------------
[2014-06-11 18:08:00] tom at r dot je
Description:
------------
At the moment, calling ReflectionClass::newInstanceWithoutConstructor() on an internal class results
in the error:
Class $name is an internal class that cannot be
instantiated without invoking its constructor
For example:
<?php
$reflect = new ReflectionClass('exception');
$myException = $reflect->newInstanceWithoutConstructor();
?>
Will create the error:
Class Exception is an internal class that cannot be instantiated without invoking its constructor.
That's fine (although a bizarre restriction!) because I can work around it using
ReflectionClass()::isInternal():
<?
$reflect = new ReflectionClass('Exception');
if ($reflect->isInternal()) {
$reflect->newInstanceWithoutConstructor();
}
?>
However, if a class extends an internal class, there's no way to easily detect whether
newInstanceWithoutConstructor() will be allowed or not.
<?php
class MyException extends Exception {
}
$reflect = new ReflectionClass('MyException');
if ($reflect->isInternal()) {
$reflect->newInstanceWithoutConstructor();
}
?>
This breaks with the same arbitrary restriction Class Exception is an internal class that cannot be
instantiated without invoking its constructor.
The only way to currently fix this is to loop back through every parent using
<?php
class MyException extends Exception {
}
$reflect = new ReflectionClass('MyException');
$parent = clone $reflect;
while ($parent->getParentClass()) {
$parent = $parent->getParentClass();
}
if ($parent->isInternal() {
$reflect->newInstanceWithoutConstructor();
}
?>
This is needlessly verbose.
In an ideal world, I'd like to see the arbitrary restriction applied to internal classes
removed entirely and allow them to be created without a constructor.
However, I'm guessing there's a technical reason for that not being feasible so instead,
I'd suggest adding a ReflectionClass::getRootClass() method, which
retrieved the top level parent and you could do:
<?php
$reflect = new ReflectionClass('MyException');
if ($reflect->getRootClass()->isInternal()) {
$reflect->newInstanceWithoutConstructor();
}
?>
For top level classes, getRootClass should return itself (the root class of Exception should return
new ReflectionClass('Exception') )
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=67422&edit=1