2012-01-04 223 views
12

我知道可以使用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]); 
+0

你的问题有点模棱两可。这听起来像是你说现在你不知道构造函数会带来多少个参数,但是它的数量会在运行时被修复,并且你想用正确的数字来调用它。那是对的吗? – 2012-01-04 22:00:25

+0

@jburbage是...要实例化的类的名称以及构造函数的参数将被定义。我从另一个来源获取这些信息。为了简单起见,我将其从此代码中删除。我要评论上面的代码来澄清。 – bmarti44 2012-01-04 22:06:07

+3

你见过[这个问题](http://stackoverflow.com/questions/1569949/instantiating-a-new-php-class-with-one-or-many-arguments)?那里的答案可能会解决你的问题。 – 2012-01-04 22:07:04

回答

37

您可以执行以下操作使用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你可以用Argument unpacking实现这一目标。

$myClass = '\Some\Dynamically\Generated\a'; 
$myParameters = ['dynamicparam1', 'dynamicparam2']; 

$myClassInstance = new $myClass(...$myParameters); 
+0

这实际上是我最终需要使用的。我只是想知道是否使用ReflectionClass最终会让我的代码变慢。 – bmarti44 2012-01-05 15:28:51

+2

@ bmarti44它取决于你将如何使用它!这里有两个关于ReflectionClass性能的链接http://stackoverflow.com/questions/294582/php-5-reflection-api-performance和http://blog.liip.ch/archive/2008/09/18/fotd- reflectionclass-newinstanceargs-args-is-slow.html如果它降低了代码性能,则可以缓存类结构。 – satrun77 2012-01-05 19:38:18

7

我实现这种方法时,很多函数参数是> 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索引数组。在构造数组时需要非常小心,并且考虑具有含义的索引,否则您将传递一个带有偏移参数的数组,并破坏您的函数。

+0

我会使用这种方法,但是。 。 。其中一个类正在使用需要两个参数,而不是由我写的。 。 。所以我需要去使用ReflectionClass。不过,谢谢你的这种方法,我相信我们会在所有新创建的类中使用它。 – bmarti44 2012-01-05 15:30:18

+0

我也使用了这个方法,但是,我只使用'$ options'数组来严格限制_optional_参数,并允许_compiler_在方法调用中断开缺少的必需参数。 – MrWhite 2014-05-14 09:47:10

0

您可以使用func_get_args()来做到这一点。

​​

基本上,你简直就是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 

希望有所帮助。

0

我已经在这里找到

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

的例子:

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

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

相关问题