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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: vituko at gmail dot com
New email:
PHP Version: OS:

 

 [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: Sat Dec 21 12:01:31 2024 UTC