16

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

3
  • Not related to your question, but $args will always be isset since you assign array() into it in the function definition. You may be interested in empty, or $args = null. Commented Dec 7, 2009 at 6:43
  • I m sorry, this is also not related to your question, but what you are doing is not cool. the answer to your question is : let your constructor takes an array, have some class attributes, then process the array and map it to the class attributes. But again, you are doing something that s not cool. Commented Dec 7, 2009 at 6:50
  • the test class and other are to be made by other developers using their own way with arguments and without it, so i don't want to restrict them to only pass arguments as array to constructors. Commented Dec 7, 2009 at 7:14

6 Answers 6

33

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);
}
Sign up to request clarification or add additional context in comments.

2 Comments

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 :)
I was searching for a non-reflection base solution, but look like I had to resort to this. Darn.
4

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

Comments

1

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();

1 Comment

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).
1
class textProperty
{
    public $start;
    public $end;
    function textProperty($start, $end)
    {
        $this->start = $start;
        $this->end = $end;
    }

}

$object = new textProperty($start, $end);

don't work?

Comments

0

The easiest way I have found:

if ($depCount === 0) {
            $instance = new $clazz();
        } elseif ($depCount === 1) {
            $instance = new $clazz($depInstances[0]);
        } elseif ($depCount === 2) {
            $instance = new $clazz($depInstances[0], $depInstances[1]);
        } elseif ($depCount === 3) {
            $instance = new $clazz($depInstances[0], $depInstances[1], $depInstances[2]);
        }

Sorry a bit raw, but you should understand the idea.

Comments

0

We're in 2019 now and we have php7 now... and we have the spread-operator (...) . We can now simply call

<?php

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

        if (isset($args))
        {
            $class_instance = new $file_name(...$args); // <-- notice the spread operator
        }
        else
        {
            $class_instance = new $file_name();
        }

        return $class_instance;
    }
}


Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.