php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67422 Cannot determine whether newInstanceWithoutConstructor can be used
Submitted: 2014-06-11 18:08 UTC Modified: 2015-01-16 19:33 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: tom at r dot je Assigned: danack (profile)
Status: Closed Package: Reflection related
PHP Version: 5.5.13 OS:
Private report: No CVE-ID: None
 [2014-06-11 18:08 UTC] 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') )







Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-12 09:32 UTC] tom at r dot je
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.
 [2015-01-16 19:33 UTC] danack@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: danack
 [2015-01-16 19:33 UTC] danack@php.net
This was fixed in PHP 5.6

<?php
class Foo extends Exception {}

$reflect = new ReflectionClass('Foo');
if ($reflect->isInternal()) {
    echo "Cannot make, is internal class\n";
}
else {
    echo "Safe to make.\n";
    $reflect->newInstanceWithoutConstructor();
}

?>

PHP 5.6+ output is: "Safe to make." without any error.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Apr 24 04:01:30 2024 UTC