如何安全地动态创建现有PHP类的实例?

时间:2010-09-06 14:31:12

标签: php dynamic instantiation

说我有一个文件Foo.php:

<?php
interface ICommand
{
     function doSomething();
}

class Foo implements ICommand
{
    public function doSomething()
    {
        return "I'm Foo output";
    }
}

?>

如果我想创建一个类型为Foo的类,我可以使用:

require_once("path/to/Foo.php") ;
$bar = new Foo(); 

但是说我创建了一个Chain of Command Pattern并且我有一个配置文件来注册所有可能的类,并根据配置文件中存在的字符串创建这些类的实例。

register("Foo", "path/to/Foo.php");

function register($className, $classPath)
{
    require_once($classPath); //Error if the file isn't included, but lets 
                              //assume that the file "Foo.php" exists.
    $classInstance = new $className; //What happens here if the class Foo isn't 
                                     //defined in the file "Foo.php"? 

    $classInstance->doSomething(); //And what happens here if this code is executed at
                                   //all?
    //Etc...
}

如何确保这些类实际上是配置文件所在的位置?如果一个类不存在(但文件是)会发生什么,它会创建一个动态生成的类的实例,没有进一步的描述吗?

2 个答案:

答案 0 :(得分:4)

您可以使用class_exists检查是否已定义类。

如果你动态地调用一个类并且在同一个函数中调用该类的方法,你可能也希望动态调用该方法(除非你的所有类都有完全相同的方法。如果是这样的话,您也可以使用method_exists

最后,您还可以使用file_exists确保可以包含该文件:

register("Foo", "path/to/Foo.php", "bar", array('arg1', 'arg2'));

function register($className, $classPath, $methodName, $args)
{
    if(!file_exists($classPath)) return false;

    require_once($classPath);

    if(!class_exists($className)) return false;

    $classInstance = new $className;

    if(!method_exists($classInstance, $methodName)) return false;

    $classInstance->$methodName($args);
}

答案 1 :(得分:1)

如果您尝试实例化未定义的类,例如

$o = new IsNotDefined();

调用autoloader并将类的名称作为参数传递。如果注册的自动加载器提供该类的实现,则脚本将“正常”继续。如果没有提供类的实现,php将停止Fatal error: Class 'IsNotDefined' not found

您可能也对

感兴趣