php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #44604 newInstanceArgs (ReflectionClass) and visibility
Submitted: 2008-04-02 08:14 UTC Modified: 2015-03-27 14:42 UTC
Votes:8
Avg. Score:4.6 ± 0.7
Reproduced:7 of 7 (100.0%)
Same Version:4 (57.1%)
Same OS:6 (85.7%)
From: vituko at gmail dot com Assigned:
Status: Not a bug Package: Reflection related
PHP Version: 5.3CVS-2008-04-02 (CVS) OS: Debian GNU/Linux
Private report: No CVE-ID: None
 [2008-04-02 08:14 UTC] vituko at gmail dot com
Description:
------------
1 - call_user_func_array ($ref_f, $taboa) ;

Here, the visibility is computed from the context where this 
function is called.

2 - $obx -> newInstanceArgs ($taboa) ;

ReflectionException : Access to non-public constructor of class ...
Constructor must be public anyway.

So ... eval is not so bad.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-04-03 11:23 UTC] jani@php.net
And the bug here is...?
 [2008-04-04 14:06 UTC] vituko at gmail dot com
I didn't say it was a bug.

I only said that it is a limitation... maybe easy to change.

ReflectionClass -> newInstanceArgs is very nice but only works with public constructors. If a class constructor is private, for example, you cannot instantiate it with this method, even from this class scope.

The same example with call_user_func_array, you change the constructor with another method and it works... But this function doesn't allow to instantiate an object (you can only call a parent constructor on an already instantiated object).

So, in this context (a class with a private/protected constructor), the only way of instantiating it with an arbitrary number of arguments is to build a string and use eval... not very nice nor performant.

Thanks
 [2008-04-04 18:00 UTC] jani@php.net
Reclassified. NOTE: Discussion about this should be done on the internals mailing list..
 [2011-04-08 21:24 UTC] jani@php.net
-Package: Feature/Change Request +Package: Reflection related
 [2011-04-08 21:24 UTC] jani@php.net
-Summary: newInstanceArgs (ReflectionClass) and visivility +Summary: newInstanceArgs (ReflectionClass) and visibility
 [2013-11-20 10:39 UTC] jerome at taotesting dot com
I would also argue that such a feature would be absolutely great for Unit Testing. If method calls can be done on protected/private methods via ReflectionMethod::setAccessible(), why not allow that with private constructors?

All the best,
Jérôme
 [2013-11-20 11:02 UTC] requinix@php.net
As of PHP 5.4 you can use ReflectionClass::newInstanceWithoutConstructor() and manually invoke the constructor.

$rc = new ReflectionClass("foo");
$obj = $rc->newInstanceWithoutConstructor();
$ctor = $rc->getConstructor();
if ($ctor) { // constructors are optional!
    $ctor->setAccessible(true);
    $ctor->invoke($obj);
}

A couple more function calls seems a small price to pay for the ability to do something the class itself specifically tried to prohibit you from doing.
 [2013-11-20 12:40 UTC] jerome at taotesting dot com
Thanks a lot for this reply !

Even if from a pure OOP perspective, it looks strange to me... If it works, I'm can go with it !

To be a little bit more precise about why such a feature is important in a unit testing context:

When implementing pure Composition (strong aggregation), it is forbidden to instantiate a composite class if container is not instantiated. However, if you work in a bottom to top approach, you'll have to be able to instantiate this composite class for testing, before to program and test the container class.

Bests
 [2015-03-27 14:42 UTC] tyrael@php.net
-Status: Open +Status: Not a bug
 [2015-03-27 14:42 UTC] tyrael@php.net
marking this not a bug, in 5.6 we extended the list of classes allowed to be instantiated through newInstanceWithoutConstructor, if you have something else in mind to improve the current situation, please open a new issue as feature request.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 13 17:01:27 2024 UTC