Mark
Mark

Reputation: 1417

Yii2 dynamically loading class from name

I struggle with this problem for a while - and the reason is probably trivial.

Background

I've created parser module for my Yii2 application so I can call it from other places (mobile app, etc.) to get data from various websites. There may be many parser classes, all implementing same interface.

Project structure

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

I've removed some code for better readability.

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

Right now everything works more or less ok, so I guess I'm importing correct namespaces. But when I remove return new SampleParser(); and let the object to be created by string name, it fails with error:

PHP Fatal Error – yii\base\ErrorException

Class 'SampleParser' not found

with highlighted line:

$object = new $className();

What am I doing wrong here? Thanks!

Upvotes: 2

Views: 1847

Answers (1)

Bizley
Bizley

Reputation: 18021

Try again with help of Yii:

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

Remember that ensure() throws \yii\base\InvalidConfigException when passed reference is not of the type you expect so you need to catch it at some point.

If you are using PHP < 5.5 instead of IParseProvider::class you can use full class name with it's namespace.

P.S. remove use app\modules\parser\components\parsers; unless you have got class named parsers you want to use.

Upvotes: 3

Related Questions