views:

756

answers:

3

Hello All,

I am in a situations where i need to instantiate a class with arguments from within an instance of another class. Here is the prototype:

//test.php

class test
{
 function __construct($a, $b, $c)
 {
  echo $a . '<br />';
  echo $b . '<br />';
  echo $c . '<br />';
 }
}

Now, i need to instantiate above class using below class's cls function:

class myclass
{
function cls($file_name, $args = array())
{
 include $file_name . ".php";

 if (isset($args))
 {
  // this is where the problem might be, i need to pass as many arguments as test class has.
  $class_instance = new $file_name($args);
 }
 else
 {
  $class_instance = new $file_name();
 }

 return $class_instance;
}
}

Now when i try to create an instance of test class while passing arguments to it:

$myclass = new myclass;
$test = $myclass->cls('test', array('a1', 'b2', 'c3'));

It gives error: Missing argument 1 and 2; only first argument is passed.

This works fine if i instantiate a class which has no arguments in it's constructor function.

For experienced PHP developers, above should not be much of a problem. Please help.

Thanks

+1  A: 

You can:

1) Modify test class to accept an array, which contains the data you wish to pass.

//test.php

class test
{
        function __construct($a)
        {
                echo $a[0] . '<br />';
                echo $a[1] . '<br />';
                echo $a[2] . '<br />';
        }
}

2) initiate using a user method instead of the constructor and call it using the call_user_func_array() function.

//test.php

class test
{
        function __construct()
        {

        }

        public function init($a, $b, $c){
                echo $a . '<br />';
                echo $b . '<br />';
                echo $c . '<br />';
        }

}

In your main class:

class myclass
{
function cls($file_name, $args = array())
{
        include $file_name . ".php";

        if (isset($args))
        {
                // this is where the problem might be, i need to pass as many arguments as test class has.
                $class_instance = new $file_name($args);
                call_user_func_array(array($class_instance,'init'), $args);
        }
        else
        {
                $class_instance = new $file_name();
        }

        return $class_instance;
}
}

http://www.php.net/manual/en/function.call-user-func-array.php

Lastly, you can leave your constructor params blank and use func_get_args().

//test.php

class test
{
        function __construct()
        {
                $a = func_get_args();
                echo $a[0] . '<br />';
                echo $a[1] . '<br />';
                echo $a[2] . '<br />';
        }
}

http://sg.php.net/manual/en/function.func-get-args.php

thephpdeveloper
A: 

You could use call_user_func_array() I believe.

or you could leave the arguments list of the constructor, and then inside the constructor use this

$args = func_get_args();
alex
The first part of this answer helps with calling the constructor; the second part could help in this class to make the interface nicer (just pass the arguments instead of wrapping them in an array).
Tordek
+4  A: 

you need Reflection http://php.net/manual/en/class.reflectionclass.php

if(count($args) == 0)
   $obj = new $className;
else {
   $r = new ReflectionClass($className);
   $obj = $r->newInstanceArgs($args);
}
stereofrog
I am really inspired with the knowledge that stereofrog has because most people don't even know about the reflection class and i myself did not know that we can use the reflection class to pass arguments that way. it solved my problem i was not able to find the solution to for many days. Even the most experienced developers were not able to provide satisfactory answer to my question which is very important and everyone here should look at that scenario of the question. Anyways I am very happy to find a solution to this very important question. Thanks stereofrog :)
Sarfraz
you're welcome ;)
stereofrog
I was searching for a non-reflection base solution, but look like I had to resort to this. Darn.
yclian