2017-02-17 16 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){ 

    } 
} 

今すべてが多かれ少なかれOK働くので、私は私が正しい名前空間をインポートしていますね。しかし、私はreturn new SampleParser();を削除して、オブジェクトが文字列名によって作成されるようにしましょうと、それはエラーで失敗します。強調表示されたラインと

PHP Fatal Error – yii\base\ErrorException

Class 'SampleParser' not found

を:

$object = new $className();

私はここで間違って何をしているのですか?ありがとう!

答えて

2

はYiiのの助けを借りてもう一度お試しください:

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

は、渡されたリファレンスはあなたがそうあなたには、いくつかの時点でそれをキャッチする必要が期待するタイプではない場合ensure()\yii\base\InvalidConfigExceptionをスローすることを忘れないでください。

IParseProvider::classの代わりにPHP < 5.5を使用している場合は、その名前空間で完全なクラス名を使用できます。

P.S.使用したいクラスparsersを持っていなければ、use app\modules\parser\components\parsers;を削除してください。

+0

ありがとうございました。ところで、あなたのメソッドは、 '未定義のメソッドapp \ modules \ parser \ models \ IParseProvider :: className()'を呼び出します。私がインターフェイスと 'SampleParser'の両方に静的' className() 'メソッドを含めると'抽象メソッドapp \ modules \ parser \ models \ IParseProvider :: className() 'を呼び出せません。 – Mark

+1

ああ、申し訳ありません、あなたのクラスは 'yii \ base \ Object'を拡張していないことを忘れています - PHP> = 5.5を使用しているなら' IParseProvider :: class'を使うことができます – Bizley

+0

それは動作します! 'IParseProvider :: className()'の代わりに 'IParseProvider :: class'がその仕事をしました。ありがとうございました:)この情報をあなたの答えに加えて、私はそれを受け入れることができます。 – Mark

関連する問題