2017-02-17 2 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

Попробуйте снова с помощью Yii:

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

Спасибо, я удалил ненужное использование. BTW ваш метод вызывает «вызов неопределенного метода app \ modules \ parser \ models \ IParseProvider :: className()» - и это правильно, это просто чистый интерфейс. Когда я включаю статический метод 'className()' как в интерфейсе, так и в 'SampleParser', я получаю' Не могу вызвать приложение абстрактного метода \ modules \ parser \ models \ IParseProvider :: className() '. – Mark

+1

О, извините, я забыл, что ваш класс не расширяет 'yii \ base \ Object' - вы можете использовать' IParseProvider :: class', если вы используете PHP> = 5.5 – Bizley

+0

Он работает! 'IParseProvider :: class' вместо' IParseProvider :: className() 'выполнил задание. Большое спасибо :) Пожалуйста, добавьте эту информацию в свой ответ, чтобы я мог ее принять. – Mark