callable (instance-method, static-method, function, lamdba/closure) with an arbitrary number of arguments.
- class TestClass1 {
- public static function argsToArray($arg1, $arg2, $arg3){
- }
- }
- // array(1,2,3)
However this function has one drawback since it doesnt support the creation of an object
through its class´ constructor.
The following code will not construct a new TestClass2 instance, but result in a warning:
"call_user_func_array() expects parameter 1 to be a valid callback, non-static method
TestClass2::__construct() cannot be called statically in [...]"
- class TestClass2 {
- public function __construct($arg1, $arg2, $arg3){
- [...]
- }
- }
- // null
Luckily there are some solutions to this problem:
The "nasty, ugly and evil approach"
This solution is definitely not recommended (at least when you are on PHP5 or higher),
since it relies on the execution of dynamically created code through the 'eval' function.
This is not safe nor reliable, however it´s the only way to do the magic in PHP4.
- class TestClass3 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- }
- function call_constructor_array_eval($cls, $arguments){
- return $obj;
- }
- // object(TestClass3)[1]
- // public 'arg1' => int 1
- // public 'arg2' => int 2
- // public 'arg3' => int 3
The "Reflection approach"
Luckily PHP5 introduced back then the Reflection set of classes, which can be used to
examine and reverse-engineer classes, functions, methods, etc. Additionally the Reflection
classes provide delegate methods to call on methods or functions.
In this (recommended) approach, we use 'newInstanceArgs' method of ReflectionClass,
which gives us a clean and reliable way to construct objects dynamically.
- class TestClass4 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- }
- function call_constructor_array_reflection($cls, $arguments){
- $rc = new ReflectionClass('TestClass');
- return $rc->newInstanceArgs($arguments);
- }
- // object(TestClass4)[1]
- // public 'arg1' => int 7
- // public 'arg2' => int 8
- // public 'arg3' => int 9
The "polymorphic approach"
This last solution is just a variation of the "Reflection approach", but it serves in places
where a (building) part of application should not be aware of wether it´s calling a native
constructor or an arbitrary method ('build', 'getInstance', etc.). For the latter we have to
use call_user_func_array in any way and it´s very simple to make the "Reflection approach"
work in the same way.
- class TestClass5 {
- public function __construct($arg1, $arg2, $arg3){
- $this->arg1 = $arg1;
- $this->arg2 = $arg2;
- $this->arg3 = $arg3;
- }
- public function argsToArray($arg1, $arg2, $arg3){
- }
- }
- $rc = new ReflectionClass('TestClass5');
- // object(TestClass5)[1]
- // public 'arg1' => string 'a' (length=1)
- // public 'arg2' => string 'b' (length=1)
- // public 'arg3' => string 'c' (length=1)
- //array
- // 0 => string 'x' (length=1)
- // 1 => string 'y' (length=1)
- // 2 => string 'z' (length=1)


I'd almost come to the conclusion that this wasn't possible.
It even works on the clunky old CentOS 5.5 with PHP 5.1.6 I'm forced to use at work!