Yii2从名称动态加载类

时间:2017-02-17 06:33:54

标签: php yii2

我在这个问题上挣扎了一段时间 - 原因可能很简单。

背景

我为我的Yii2应用程序创建了解析器模块,因此我可以从其他地方(移动应用程序等)调用它来从各种网站获取数据。可能有许多解析器类,都实现相同的接口。

项目结构

...
/modules
    \_ parser
        \_components
            \_parsers
                \_SampleParser.php
        \_controllers
            \_DefaultController.php
        \_Parser.php
...

我删除了一些代码以提高可读性。

DefaultController.php:

namespace app\modules\parser\controllers;

use Yii;
use yii\web\Controller;
use app\modules\parser\components\parsers;
use app\modules\parser\components\parsers\SampleParser;

/**
 * Default controller for the `parser` module
 */
class DefaultController extends Controller
{

    private function loadParser($parserName){

        return new SampleParser();  // if I leave this here, everything works okay
        $className = $parserName.'Parser';
        $object = new $className();
        if ($object instanceof IParseProvider){
            return $object;
        }
    }

...
     public function actionIndex()
    {
        $url = "http://google.com";
        $parser = 'Sample';
        $loadedParser = $this->loadParser($parser);
        $response = $loadedParser->parse($url); 


        \Yii::$app->response->format = 'json';
        return $response->toJson();
    }
...

SampleParser.php:

<?php
namespace app\modules\parser\components\parsers;

use app\modules\parser\models\IParseProvider;

class SampleParser implements IParseProvider {

    public function canParse($url){

    }

    public function parse($url){

    }
}

现在一切都或多或少都可以,所以我想我正在导入正确的命名空间。但是当我删除return new SampleParser();并让对象通过字符串名称创建时,它会失败并显示错误:

  

PHP致命错误 - yii \ base \ ErrorException

     

未找到类'SampleParser'

带突出显示的行:

  

$ object = new $ className();

我在这里做错了什么?谢谢!

1 个答案:

答案 0 :(得分:2)

在Yii的帮助下再试一次:

private function loadParser($parserName)
{
    return \yii\di\Instance::ensure(
        'app\modules\parser\components\parsers\\' . $parserName . 'Parser',
        IParseProvider::class
    );
}

请记住ensure()在传递引用时抛出\yii\base\InvalidConfigException不是您期望的类型,因此您需要在某个时刻捕获它。

如果您使用的是PHP&lt; 5.5而不是IParseProvider::class,您可以使用完整的类名称及其命名空间。

P.S。删除use app\modules\parser\components\parsers;,除非您有一个名为parsers的课程。