2012-01-04 226 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; 
} 

但有人告訴我,如果有與受保護的構造函數的類的例子嗎?

相關問題