2017-02-17 57 views
2

我在這個問題上掙扎了一段時間 - 原因可能是微不足道的。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 Fatal Error – yii\base\ErrorException

Class 'SampleParser' not found

與突出顯示的行:

$object = new $className();

我在做什麼錯在這裏?謝謝!

回答

2

與誼的幫助,請再試一次:

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

記住ensure()拋出\yii\base\InvalidConfigException時傳遞的引用是你期望,所以你必須抓住它在某些時候的類型不。

如果您使用PHP < 5.5而不是IParseProvider::class,則可以使用完整的類名稱及其名稱空間。

P.S.刪除use app\modules\parser\components\parsers;,除非您有要使用的類名爲parsers的類。

+0

謝謝,我已經刪除了不必要的使用。順便說一句,你的方法引發'調用未定義的方法app \ modules \ parser \ models \ IParseProvider :: className()' - 那是正確的,那只是純粹的接口。當我在接口和SampleParser中都包含靜態'className()'方法時,我得到'不能調用抽象方法app \ modules \ parser \ models \ IParseProvider :: className()'。 – Mark

+1

噢,對不起,我忘記了你的課程沒有擴展'yii \ base \ Object' - 如果你使用的是PHP> = 5.5 – Bizley

+0

,你可以使用'IParseProvider :: class'它可行! 'IParseProvider :: class'代替'IParseProvider :: className()'完成了這項工作。非常感謝:)請將這些信息添加到您的答案,以便我可以接受它。 – Mark