在PHP中使用动态变量实例化对象的含义

Ala*_*orm 11 php oop performance

使用以下表单在PHP中声明新类实例的性能,安全性或"其他"含义是什么?

<?php
  $class_name = 'SomeClassName';
  $object = new $class_name;
?>
Run Code Online (Sandbox Code Playgroud)

这是一个人为的例子,但我在工厂(OOP)中看到过这种形式,以避免使用大的if/switch语句.

立刻想到的问题是

  1. 你失去了将参数传递给构造函数的能力(LIES.感谢Jeremy)
  2. 闻起来像eval(),它带来了所有安全问题(但不一定是性能问题?)

还有什么其他含义,或者除了"Rank PHP Hackery"之外的什么搜索引擎术语可以用来研究这个?

Jer*_*ten 8

看起来你仍然可以将参数传递给构造函数,这是我的测试代码:

<?php

class Test {
    function __construct($x) {
        echo $x;
    }
}

$class = 'Test';
$object = new $class('test'); // echoes "test"

?>
Run Code Online (Sandbox Code Playgroud)

这就是你的意思,对吗?

所以你提到的唯一另一个问题是我可以想到的是它的安全性,但要保证它的安全性并不是太难,而且它显然比使用eval()更安全.


pil*_*lif 8

在运行时解决问题的一个问题是你使操作码缓存(如APC)变得非常困难.不过,就目前而言,如果在实例化时需要一定量的间接,那么在你的问题中做一些像你描述的那样是一种有效的方法.

只要你不做那样的事情

$classname = 'SomeClassName';
for ($x = 0; $x < 100000; $x++){
  $object = new $classname;
}
Run Code Online (Sandbox Code Playgroud)

你可能没事:-)

(我的观点是:在这里动态地查找一个班级然后不会受到伤害.如果你经常这样做,它会).

另外,请确保永远不能从外部设置$ classname - 您希望能够控制将要实例化的确切类.


Sel*_*aek 5

我想补充一点,您还可以使用以下动态数量的参数对其进行实例化:

<?php

$class = "Test";
$args = array('a', 'b');
$ref = new ReflectionClass($class);
$instance = $ref->newInstanceArgs($args);

?>
Run Code Online (Sandbox Code Playgroud)

但是,当然这样做会增加一些开销.

关于安全问题我认为这不重要,至少与eval()相比没什么.在最坏的情况下,错误的类会被实例化,当然这是一个潜在的安全漏洞,但是更难以利用,并且如果您确实需要用户输入来定义类名,则可以使用允许的类数组进行过滤.