在构造函数中动态调用带有可变数量参数的Class


Dynamically call Class with variable number of parameters in the constructor

我知道可以使用call_user_func_array()调用具有可变数量参数的函数-> http://php.net/manual/en/function.call-user-func-array.php。我想做的几乎是相同的,但不是一个函数,我想调用一个PHP类,在它的构造函数中有可变数量的参数。

它会像下面这样工作,但我不知道参数的数量,所以我不知道如何实例化类。

<?php
//The class name will be pulled dynamically from another source
$myClass = ''Some'Dynamically'Generated'Class';
//The parameters will also be pulled from another source, for simplicity I
//have used two parameters. There could be 0, 1, 2, N, ... parameters
$myParameters = array ('dynamicparam1', 'dynamicparam2');
//The instantiated class needs to be called with 0, 1, 2, N, ... parameters
//not just two parameters.
$myClassInstance = new $myClass($myParameters[0], $myParameters[1]);

您可以使用ReflectionClass

执行以下操作
$myClass = ''Some'Dynamically'Generated'a';
$myParameters = array ('dynamicparam1', 'dynamicparam2');
$reflection = new 'ReflectionClass($myClass); 
$myClassInstance = $reflection->newInstanceArgs($myParameters); 
PHP手册:http://www.php.net/manual/en/reflectionclass.newinstanceargs.php <标题>编辑:

在php 5.6中,你可以通过参数解包实现。

$myClass = ''Some'Dynamically'Generated'a';
$myParameters = ['dynamicparam1', 'dynamicparam2'];
$myClassInstance = new $myClass(...$myParameters); 

当函数参数> 2时,我经常实现这种方法,而不是以必须按特定顺序排列的参数圣诞列表结束,我只是传递一个关联数组。通过传递一个关联数组,我可以检查必要的和可选的参数,并根据需要处理缺失的值。比如:

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

我强烈建议使用关联数组,但是也可以使用0索引数组。在构造数组和考虑有意义的索引时,您必须非常小心,否则您将传入一个带有偏移参数的数组,并破坏您的函数。

您可以使用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" );

基本上,您只需将func_get_args的结果传递给类的构造函数,并让它决定是否使用该函数的参数数组调用它,或者是否正常调用它。

此代码输出

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

希望对你有帮助。

我发现这里

是否有一个call_user_func()等价于创建一个新的类实例?

例子:

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

但是有人能告诉我,如果有一个例子与受保护的构造函数类?