Dynamically call Class with variable number of parameters in the constructor

后端 未结 4 1171
广开言路
广开言路 2020-12-09 10:35

I know that it is possible to call a function with a variable number of parameters with call_user_func_array() found here -> http://php.net/manual/en/function.call-user-func

相关标签:
4条回答
  • 2020-12-09 10:36

    I implement this approach a lot when function args are > 2, rather then end up with an Christmas list of arguments which must be in a specific order, I simply pass in an associative array. By passing in an associative array, I can check for necessary and optional args and handle missing values as needed. Something like:

    class MyClass
    {
        protected $requiredArg1;
        protected $optionalArg1;
    
        public function __construct(array $options = array())
        {
            // Check for a necessary arg
            if (!isset($options['requiredArg1'])) {
                throw new Exception('Missing requiredArg1');
            }
    
            // Now I can just localize
            $requiredArg1 = $options['requiredArg1'];
            $optionalArg1 = (isset($options['optionalArg1'])) ? $options['optionalArg1'] : null;
    
            // Now that you have localized args, do what you want
            $this->requiredArg1 = $requiredArg1;
            $this->optionalArg1 = $optionalArg1;            
        }
    }
    
    // Example call
    $class = 'MyClass';
    $array = array('requiredArg1' => 'Foo!', 'optionalArg1' => 'Bar!');
    
    $instance = new $class($array);
    
    var_dump($instance->getRequiredArg1());
    var_dump($instance->getOptionalArg1());
    

    I highly recommend using an associative array, however it is possible to use a 0-index array. You will have to be extremely careful when constructing the array and account for indices that have meaning, otherwise you will pass in an array with offset args and wreck havoc with your function.

    0 讨论(0)
  • 2020-12-09 10:40

    I've found here

    Is there a call_user_func() equivalent to create a new class instance?

    the example:

    function createInstance($className, array $arguments = array())
    {
        if(class_exists($className)) {
            return call_user_func_array(array(
                new ReflectionClass($className), 'newInstance'), 
                $arguments);
        }
        return false;
    }
    

    But can somebody tell me if there is an example for classes with protected constructors?

    0 讨论(0)
  • 2020-12-09 10:59

    You can do the following using ReflectionClass

    $myClass = '\Some\Dynamically\Generated\a';
    $myParameters = array ('dynamicparam1', 'dynamicparam2');
    
    $reflection = new \ReflectionClass($myClass); 
    $myClassInstance = $reflection->newInstanceArgs($myParameters); 
    

    PHP manual: http://www.php.net/manual/en/reflectionclass.newinstanceargs.php

    Edit:

    In php 5.6 you can achieve this with Argument unpacking.

    $myClass = '\Some\Dynamically\Generated\a';
    $myParameters = ['dynamicparam1', 'dynamicparam2'];
    
    $myClassInstance = new $myClass(...$myParameters); 
    
    0 讨论(0)
  • 2020-12-09 11:03

    You can do that using func_get_args().

    class my_class {
        function __construct( $first = NULL ) {
            $params = func_get_args();
            if( is_array( $first ) ) 
                $params = $first;
            // the $params array will contain the 
            // arguments passed to the child function
            foreach( $params as $p )
                echo "Param: $p\n";
        }
    }
    function my_function() {
        $instance = new my_class( func_get_args() );
    }
    
    echo "you can still create my_class instances like normal:";
    $instance = new my_class( "one", "two", "three" );
    echo "\n\n\n";
    echo "but also through my_function:";
    my_function( "one", "two", "three" );
    

    Basically, you simply pass the result of func_get_args to the constructor of your class, and let it decide whether it is being called with an array of arguments from that function, or whether it is being called normally.

    This code outputs

    you can still create my_class instances like normal: 
    Param: one
    Param: two
    Param: three
    
    but also through my_function: 
    Param: one
    Param: two
    Param: three
    

    Hope that helps.

    0 讨论(0)
提交回复
热议问题