I'd like to be able to create an object with a variable number of parameters:

$myObject = new object($param1, $param1, $param3, ...etc);

So far I have been unsuccessful in my searches. I already know I can use a variable number of parameters when calling a method within that object:

$methodParameterArray = array('param1','param2','param3');
$run = call_user_func_array(array($myObject, 'myMethod'), $methodParameterArray);

Is there anything similar that I could do when creating the object?

    Something like this?

    <?php
    class MyClass
    {
       public $params = array ();
       public function __construct()
       {
          $this->params = func_get_args();
       }
    }
    
    $test = new MyClass('test1', 'test2', array ('foo', 'bar'));
    echo "<pre>".print_r($test, 1)."</pre>";
    
    /* OUTPUT:
    MyClass Object
    (
       [params] => Array
       (
          [0] => test1
          [1] => test2
          [2] => Array
          (
             [0] => foo
             [1] => bar
          )
       )
    )
    */
    ?>
    

      Thanks for the response. That would work if I always had control over the class, but for the circumstances I'm talking about, I don't always have control over the class. The assumption is that I can't modify the constuct method at all, and in fact it may be that no construct method even exists. I need a generic way to create a new object that can have 0 to infinite parameters associated with it. I need to pass an array of parameters to the new object, but the array has to bind as parameters, not as variables within a single parameter. So this WON'T work (unless the object happens to have only one parameter):

      $parameterArray = array('param1', 'param2', 'param3');
      $object = new object($parameterArray);

      I need to somehow turn $parameterArray into separate parameters, so the end result ends up looking like this:

      $object = new object('param1', 'param2', 'param3');

      And the number of parameters is unpredictable.

        I am in the process of learning but I have not come that far to understand your question.
        From my little experience this:

        I need a generic way to create a new object that can have 0 to infinite parameters associated with it.

        I read as that you want to create an object of an existing class with such a constructor, but then

        The assumption is that I can't modify the __constuct method at all

        which to me means you have to accommodate to that class constructor....

        Either you create the class and are responsible for the interface or you use an existing class with its interface but then again, I am just a beginner who probably is missing out on something important.

        Reading the post again I start to think that maybe what you mean is that you need one generic way of creating objects of different classes which are totally different.
        A kind of object creator wrapper.

          igorlopez;10890999 wrote:

          you need one generic way of creating objects of different classes which are totally different.
          A kind of object creator wrapper.

          Yes, that's exactly what I need. I'm trying to create a kind of middleware script that bridges the gap between a program (which I did not create) and miscellaneous classes (most of which I did not create).

            Here's a simplified version of the code I'm writing, which may help illustrate what I'm trying to do. The basic purpose of the script is to

            1. create a new object from a class and

            2. call a method within that object:

            <?php
            $className = isset($className) ? $className : '';
            $objectName = isset($objectName) ? $objectName : 'object';
            $objectParameters = isset($objectParameters) ? $objectParameters : ''; // expecting a comma-delimited list
            $methodName = isset($methodName) ? $methodName : '';
            $methodParameters = isset($methodParameters) ? $methodParameters : ''; // expecting a comma-delimited list
            $baseDirectory = isset($baseDirectory) ? $baseDirectory : '/path/to/base/directory/';
            $classPath = isset($classPath) ? $classPath : ''; 
            
            // Create arrays from the comma-delimited lists of parameters
            $objectParameterArray = explode(',',trim($objectParameters));
            $methodParameterArray = explode(',',trim($methodParameters));
            
            // Go get the class
            include_once($baseDirectory . $classPath);
            
            // Create a new object
            // (Note: The following line works only if there is one parameter in the class constructor.
            // I need to find a different way to do this that takes advantage of the 
            // $objectParameterArray variable.)
            ${$objectName}  = new $className($objectParameters);
            
            // Call a method within that object
            // (Note: The following line works just fine)
            $run = call_user_func_array(array(${$objectName}, $methodName), $methodParameterArray);
            
            // Output the result
            // (Note: The "echo" command assumes that the purpose of the method is to create
            // output into an HTML page. I will probably have to create some logic
            // that accounts for methods that have other purposes.)
            echo $run;
            ?>

              Perhaps you could use reflection, e.g.,

              <?php
              class X
              {
                  private $a;
              
              function __construct($a) {
                  $this->a = $a;
              }
              
              function foo() {
                  echo 'X: ' . $this->a . "<br />\n";
              }
              }
              
              class Y {
                  private $a;
                  private $b;
              
              function __construct($a, $b) {
                  $this->a = $a;
                  $this->b = $b;
              }
              
              function foo() {
                  echo 'Y: ' . $this->a . ' and ' . $this->b . "<br />\n";
              }
              }
              
              if (isset($_GET['class'])) {
                  $args = array();
                  switch ($_GET['class']) {
                  case 'X':
                      $args = array('hello');
                      break;
                  case 'Y':
                      $args = array('hello', 'world');
                      break;
                  }
              
              if (!empty($args)) {
                  $class = new ReflectionClass($_GET['class']);
                  $obj = $class->newInstanceArgs($args);
                  $obj->foo();
              } else {
                  echo 'Error: invalid class name.';
              }
              } else {
                  echo 'Specify class name using query string.';
              }
              ?>

              That said, in the above example inheritance and polymorphism and/or the use of an interface construct would be a better fit than reflection.

                I'm admittedly having a difficult time why you would want to simply ignore the defined interface of a class. It seems to run contrary to the general precepts of encapsulation in OOP. So my first suggestion would be to re-think the underlying design logic that has led you to this situation and consider whether there is a "better" means to your ends. If not, all I can think of is a sort of wrapper object.

                <?php
                class Wrapper
                {
                   public $obj;
                   public function __construct($obj, $args)
                   {
                      if(!is_object($obj))
                      {
                         throw new Exception(__METHOD__."(): Arg 1 must be an object");
                      }
                      $this->obj = $obj;
                      if(!is_array($args))
                      {
                         throw new Exception(__METHOD__."(): ARg 2 must be an array");
                      }
                      foreach($args as $key => $value)
                      {
                         $this->obj->$key = $value;
                      }
                   }
                }
                
                class Example
                {
                   public $foo;
                   public function __construct($foo)
                   {
                      $this->foo = $foo;
                   }
                   public function getFoo()
                   {
                      return $this->foo;
                   }
                }
                
                try
                {
                   $params = array('p1' => 'one', 'p2' => 'two');
                   $test = new Wrapper(new Example('bar'), $params);
                   echo "<h1>" . $test->obj->getFoo() . "</h1>\n";
                   echo "<pre>" . print_r($test, 1) . "</pre>";
                }
                catch(Exception $e)
                {
                   echo "<pre>" . print_r($e, 1) . "</pre>";
                }
                
                  12 days later
                  NogDog;10891011 wrote:

                  I'm admittedly having a difficult time why you would want to simply ignore the defined interface of a class. It seems to run contrary to the general precepts of encapsulation in OOP. So my first suggestion would be to re-think the underlying design logic that has led you to this situation and consider whether there is a "better" means to your ends. If not, all I can think of is a sort of wrapper object.

                  Thank you for the response. I had to set aside this project for a little while, which is why I haven't responded quickly, but now I'm looking at it again.

                  For the project I'm working on, the only thing I can pass to PHP is a set of parameters in text format. It's sort of like having a user submit form data and trying to use that form data to call a class. That's not exactly the case, but it's close enough for my explanation here. The code example you gave earlier is still missing the critical part that I need: the ability to create a new object with an unknown number of parameters. In your code, you wrote:

                  
                     $test = new Wrapper(new Example('bar'), $params);
                  
                  

                  Notice that you are supplying only one parameter ('bar') to the new object upon creating it. That's exactly the part that I need to fix. Somehow, I need to be able to create the object no matter how many parameters it requires. For example, the same wrapper should be able to accommodate all of these new objects:

                  • new Example2('bar', 'bar2', 'bar3')

                  • new Example3('bar', 'bar2')

                  • new Example4('bar', 'bar2', 'bar3', 'bar4', 'bar5', 'bar6')

                  That's the part that I'm having trouble figuring out.

                    You can adapt my reflection example once you have a way (e.g., [man]explode/man) to convert the text into an array of arguments.

                    EDIT:
                    Actually, you can also adapt NogDog's example by means of type checking: as with my example, you convert the text into an array of arguments. Then you check to see which class must be instantiated, and also check that the number of arguments match, then you instantiate it by directly matching the class name and the arguments.

                      pbohman;10892160 wrote:

                      ... the same wrapper should be able to accommodate all of these new objects:

                      • new Example2('bar', 'bar2', 'bar3')

                      • new Example3('bar', 'bar2')

                      • new Example4('bar', 'bar2', 'bar3', 'bar4', 'bar5', 'bar6')

                      That's the part that I'm having trouble figuring out.

                      I should mention that the list of parameters will arrive at the script in a text format, so there is a variable called $objectParameters in which a comma-delimited list of parameters will appear. For example:

                      $objectParameters="bar, bar2, bar3";

                      or

                      $objectParameters="bar, bar2";

                      or

                      $objectParameters="bar, bar2, bar3, bar4, bar5, bar6";

                      and so on. I can manipulate this list in various ways. I just don't know how to turn the list items into object parameters to be used when creating the object.

                        I just don't know how to turn the list items into object parameters to be used when creating the object.

                        How do you know which class to instantiate? When you know the class, you know its constructors and how many parameters they have, and the rest is easy.

                          laserlight;10892164 wrote:

                          How do you know which class to instantiate? When you know the class, you know its constructors and how many parameters they have, and the rest is easy.

                          One of the variables is the class name ($className); another is the class path ($classPath), so I know which object I'm trying to get. The code your originally posted used a switch function, which assumes that I know ahead of time all of the possible classes I could call, which is not the case.

                          I'm taking a look at the reflection documentation right now to see if I can understand that and make it work.

                            The code your originally posted used a switch function, which assumes that I know ahead of time all of the possible classes I could call, which is not the case.

                            True. Since I find this interesting enough, I'm going to post an improved example that takes the parameters as well. You can specify the class name and the arguments with the query string, e.g., ?class=Y&args=hello,world

                            <?php
                            class X
                            {
                                private $a;
                            
                            function __construct($a) {
                                $this->a = $a;
                            }
                            
                            function foo() {
                                echo 'X: ' . $this->a . "<br />\n";
                            }
                            }
                            
                            class Y {
                                private $a;
                                private $b;
                            
                            function __construct($a, $b) {
                                $this->a = $a;
                                $this->b = $b;
                            }
                            
                            function foo() {
                                echo 'Y: ' . $this->a . ' and ' . $this->b . "<br />\n";
                            }
                            }
                            
                            if (isset($_GET['class'], $_GET['args'])) {
                                $args = explode(',', $_GET['args']);
                                try {
                                    $class = new ReflectionClass($_GET['class']);
                                    $ctor = $class->getConstructor();
                                    if (count($args) >= $ctor->getNumberOfRequiredParameters()
                                        && count($args) <= $ctor->getNumberOfParameters()) {
                                        $obj = $class->newInstanceArgs($args);
                                        $obj->foo();
                                    } else {
                                        echo 'Error: invalid number of parameters.';
                                    }
                                } Catch (ReflectionException $e) {
                                    echo 'Error: ' . $e->getMessage();
                                }
                            } else {
                                echo 'Specify class name and comma-separated arguments using query string.';
                            }
                            ?>

                              Thank you very much for your help, laserlight. The last piece that I needed was to have a variable number of arguments for the method as well. I was able to figure out a way to do this by looking at the reflection documentation. Here's the snippet of code that I used:

                               
                              $method = new ReflectionMethod(${$objectName}, $methodName);
                              echo $method->invokeArgs(${$objectName}, $methodParameterArray);
                              

                              (One of the parameters that I receive is the object name, so I use a variable variable for that purpose.)
                              I still have to fine tune the whole thing, but you've set me on the right track. Thanks!

                                Actually, you could just write:

                                $method = $class->getMethod($methodName);
                                $method->invokeArgs($obj, $methodParameterArray);
                                  Write a Reply...