使用 class 名称作为字符串创建 class 时未找到 Class

Class not found when creating a class with class name being a string

我需要根据传递给函数的参数创建 classes。我这样做:

public function index($source)
    {
        if(in_array($source, ModuleManager::getAllModules()))
        {
            $provider = new $source();
            if($image)
            {
                return $provider->getAll(true);
            }
            else
            {
                return $provider->getAll(false);
            }
        }
    }

请注意,在第 5 行,我正在尝试创建一个 class $source 的对象,该对象肯定可用。我理解上面的代码实际上是一个 eval 调用。我正在使用 Laravel 5.2 和上面的代码 returns:

FatalThrowableError in ProcReqController.php line 19:
Fatal error: Class 'Example' not found

在上面的错误中Example可以是我犯的任何class。现在,如果我对 $source 的值进行硬编码,那么它就可以正常工作。

我遇到了什么错误?

删除实例化调用末尾的括号,我想。

看看这个 php 交互式 shell session:

php > class Foo { };
php > $fooname = 'Foo';
php > $bar = new $fooname;
php > var_dump($bar);
object(Foo)#2 (0) {
}

来源:https://whosebug.com/a/4578350/2694851

我相信发生的事情是 PHP 在您尝试实例化 class 时感到困惑,其 class 名称在变量中并且与导入有关。

解决方案 1

将您的 $class 变量设置为完全限定的 class 名称,包括命名空间,它应该可以工作。

这样,即使包含括号,new $class() 也应该可以工作。

解决方案 2

经过进一步测试,似乎当您实例化一个变量时 class,它总是采用全局命名空间。

考虑到这一点,您可以使用 class_alias 为每个 class 设置别名。在 config/app.php 中,您可以将每个 class 添加到 aliases 数组。

'aliases' => [
    ....

    'Example' => App\Example::class
]

自动加载器允许您使用 类 而无需完全限定它们...在 php 交互式 shell 中,您必须手动包含 类 并且完全使他们合格。

如果您有 Composer 项目,请转到它的目录并执行以下操作以加载原始颜色 类:

</p>

<pre><code>    set_include_path(getcwd().'/vendor/primal/color/lib/Primal/Color/');
    include 'Color.php';
    include 'Parser.php';
    include 'RGBColor.php';
    include 'HSVColor.php';
    $hello = Primal\Color\Parser::parse('#666');
    var_export($hello->toHSV());

/*
returns
Primal\Color\HSVColor::__set_state(array(
   'hue' => 0,
   'saturation' => 0,
   'value' => 37.647058823529413,
   'alpha' => 1,
))
*/