2017-02-17 5 views
2

Ich kämpfe mit diesem Problem für eine Weile - und der Grund ist wahrscheinlich trivial.Yii2 dynamisch Klasse von Name

Hintergrund

I Parser-Modul für meine Yii2 Anwendung erstellt haben, so nenne ich kann es von anderen Orten (mobile App, etc.) Daten von verschiedenen Websites. Es kann viele Parser-Klassen geben, die alle dieselbe Schnittstelle implementieren.

Projektstruktur

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

Ich habe einige Code zur besseren Lesbarkeit entfernt.

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){ 

    } 
} 

Gerade jetzt alles funktioniert mehr oder weniger ok, also denke ich, dass ich richtig bin Namespaces zu importieren. Aber wenn ich return new SampleParser(); entfernen und lassen Sie das Objekt durch string name erstellt werden, schlägt es mit Fehler:

PHP Fatal Error – yii\base\ErrorException

Class 'SampleParser' not found

mit markierten Linie:

$object = new $className();

Was mache ich falsch hier? Vielen Dank!

Antwort

2

Versuchen Sie es erneut mit Hilfe von Yü:

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

Denken Sie daran, dass ensure()\yii\base\InvalidConfigException wirft, wenn übergeben Referenz Sie also erwarten nicht von der Art ist, müssen Sie es an einem gewissen Punkt zu fangen.

Wenn Sie PHP < 5.5 anstelle von IParseProvider::class verwenden, können Sie den vollständigen Klassennamen mit seinem Namespace verwenden.

P.S. Entfernen Sie use app\modules\parser\components\parsers;, es sei denn, Sie haben die Klasse parsers, die Sie verwenden möchten.

+0

Danke, ich habe unnötige Verwendung entfernt. BTW Ihre Methode löst 'Aufruf zu undefinierter Methode app \ modules \ parser \ models \ IParseProvider :: className()' - und das ist richtig, das ist nur reine Schnittstelle. Wenn ich die static 'className()' Methode sowohl in Interface als auch in 'SampleParser' einfüge, bekomme ich' die abstrakte Methode app \ modules \ parser \ models \ IParseProvider :: className() 'nicht aufrufen können. – Mark

+1

Oh, sorry, ich vergaß Ihre Klasse nicht 'yii \ base \ Object' zu erweitern - Sie können' IParseProvider :: class' verwenden, wenn Sie PHP> = 5.5 verwenden – Bizley

+0

Es funktioniert! 'IParseProvider :: class' anstelle von' IParseProvider :: className() 'hat den Job erledigt. Vielen Dank :) Bitte fügen Sie diese Informationen zu Ihrer Antwort hinzu, damit ich sie akzeptieren kann. – Mark