2024 日本 PHP 研討會

ReflectionClass::newInstanceArgs

(PHP 5 >= 5.1.3, PHP 7, PHP 8)

ReflectionClass::newInstanceArgs使用給定的參數建立新的類別實例

說明

public ReflectionClass::newInstanceArgs(陣列 $args = []): ?物件

建立一個新的類別實例,給定的參數會傳遞給類別建構函式。

參數

args

要傳遞給類別建構函式的參數,以 陣列 形式提供。

回傳值

回傳一個新的類別實例,如果失敗則回傳 null

錯誤/例外

如果類別建構函式不是公開的,則會拋出 ReflectionException

如果類別沒有建構函式,且 args 參數包含一個或多個參數,則會拋出 ReflectionException

範例

範例 #1 ReflectionClass::newInstanceArgs() 的基本用法

<?php
$class
= new ReflectionClass('ReflectionFunction');
$instance = $class->newInstanceArgs(array('substr'));
var_dump($instance);
?>

上述範例將輸出

object(ReflectionFunction)#2 (1) {
  ["name"]=>
  string(6) "substr"
}

參見

新增註解

使用者貢獻的註解 8 則註解

kirillsaksin at no-spam dot yandex dot ru
9 年前
用於正確實例化具有私有建構函式的類別的技巧

<?php

class TestClass
{
private
$property;
private function
__construct($argument)
{
$this->property = $argument;
}
}

$ref = new ReflectionClass(TestClass::class);
$instance = $ref->newInstanceWithoutConstructor();
var_dump($instance);
echo
PHP_EOL . '------------------------' . PHP_EOL . PHP_EOL;
$constructor = $ref->getConstructor();
$constructor->setAccessible(true);
$constructor->invokeArgs($instance, ['It works!']);
var_dump($instance);

// 輸出:
// class TestClass#3 (1) {
// private $property =>
// NULL
// }
//
// ------------------------
//
// class TestClass#3 (1) {
// private $property =>
// string(9) "It works!"
// }

?>
sarfraznawaz2005 at gmail dot com
14 年前
我使用反射類別,並且偵測參數是以傳址還是傳值的方式傳遞,
然後再用這些參數成功初始化/呼叫方法。

<?php
如果 (count($args) > 1)
{
如果 (
method_exists($class_name, '__construct') === false)
{
exit(
"類別 <strong>$class_name</strong> 的建構子不存在,您不應該傳遞參數給這個類別的建構子!");
}

$refMethod = new ReflectionMethod($class_name, '__construct');
$params = $refMethod->getParameters();

$re_args = array();

foreach(
$params as $key => $param)
{
如果 (
$param->isPassedByReference())
{
$re_args[$key] = &$args[$key];
}
否則
{
$re_args[$key] = $args[$key];
}
}

$refClass = new ReflectionClass($class_name);
$class_instance = $refClass->newInstanceArgs((array) $re_args);
}
?>
richardcook at gmail dot com
15 年前
如果建構子的參數中有引用,newInstanceArgs 函式將無法呼叫類別的建構子,因此請注意傳入的內容。

<?php
類別 Foo {
函式
__construct (&$arr) {
$this->arr = &$arr;
}
函式
createInstance () {
$reflectionClass = new ReflectionClass("Bar");

return
$reflectionClass->newInstanceArgs(array($this, $this->arr));
}
函式
mod($key, $val) {
$this->arr[$key] = $val;
}
}

類別
Bar {
函式
__construct (&$foo, &$arr) {
$this->foo = &$foo;
$this->arr = &$arr;
}
函式
mod($key, $val) {
$this->arr[$key] = $val;
}
}

$arr = array();

$foo = new Foo($arr);

$arr["x"] = 1;

$foo->mod("y", 2);

$bar = $foo->createInstance();

$bar->mod("z", 3);

echo
"<pre>";
print_r($arr);
print_r($foo);
print_r($bar);
echo
"</pre>";

/*
輸出:
警告: 在 [程式碼路徑] 的第 31 行呼叫 Bar 的建構子失敗

致命錯誤: 在 [程式碼路徑] 的第 58 行呼叫非物件的 mod()
*/
?>
talk at stephensugden dot com
14 年前
這是我在我的輕量級 IoC 容器中動態實例化物件的方式

<?php

類別 SimpleContainer {

// ...

// 使用提供的參數陣列建立物件的實例
protected function instantiate($name, $args=array()){
if(empty(
$args))
return new
$name();
else {
$ref = new ReflectionClass($name);
return
$ref->newInstanceArgs($args);
}
}
// ...
}
?>

我明確地*不*處理使用者為無建構子的類別傳遞建構子參數的情況,因為我認為這*應該*會失敗。
dev at yopmail dot com
9 年前
使用 PHP 5.6,我們可以使用 ... (T_ELLIPSIS) 運算子

<?php

類別 Test {
public function
__construct($a, $b) {
echo
$a . ' ' . $b;
}
}

$args = array(12, 34);
new
Test(... $args); // 顯示 "12 34"

?>
sausage at tehsausage dot com
14 年前
煩人的是,即使您為參數傳遞一個空陣列,這也會針對沒有建構子的類別拋出異常。 對於泛型程式設計,您應該避免使用此函式,並將 call_user_func_array 與 newInstance 一起使用。
kevinpeno at gmail dot com
15 年前
我誤解了這個函式,我以為它是以陣列形式設定 Reflection::newInstance() 參數的一種方法,而不是一種建立新實例的方法。

此函式等同於 call_user_func_array(),而 Reflection::newInstance() 等同於 call_user_func()
gromit at mailinator dot com
16 年前
請注意,使用空陣列呼叫 newInstanceArgs 方法仍然會以無參數方式呼叫建構子。 如果該類別沒有建構子,則會產生異常。

您需要在呼叫此方法之前檢查建構子是否存在,或者使用 try 和 catch 來處理異常。
To Top