Using Interfaces And Di In Yii Controllers

Hi,

I wanted to work with Interfaces and Dependency Injections in my YII 1.14 project. Here is the code that I have:

The interface:




interface IUserInterface

{   

    public function DoSomething();

}



The class:




class UserService implements IUserInterface

{

    public function DoSomething()

    {

        echo "TEST TEST";

    }

}



And my controller:




class AccountController extends Controller

{	

    protected $userService;


    public function __construct(IUserInterface $userInterface) 

    {

        $this->userService = $userInterface;

        

        parent::__construct();

    }    


    public function actionTest()

    {

        $this->userService->DoSomething();

    }

}



But when I run my controller action, I get the following error: Argument 1 passed to AccountController::__construct() must be an instance of UserService, string given, called in …\framework\web\CWebApplication.php on line 359 and defined

The interface and the class are in a “services” folder and I’ve added that folder in the autoload in the config main file:




'import'=>array(

		'application.models.*',

		'application.components.*',

                'application.services.*'

	),



Do I need a dependency injector installed?

Your code can’t work.

Take a look at the constructor of CController:


public void __construct(string $id, CWebModule $module=NULL)

A controller will be created automatically by Yii and the first param will be the id, not your userservice. And the id is a string (not your interface), that causes the error.

You can’t change the constructor as you like.

You have to assign the userservice as an extra method, called somewhere in your controller (actionXY …?).

OK, but then how do I use Dependency Injection? I implemented that code based on my experience with .Net MVC (using dependency injector tool) and I thought that it will work more or less the same. How can I inject the interface in the constructor of the controller and then use its methods?

I don’t think you really need to use dependency injection. You could instead do something like this:

Config




    'components'=>array(

        'userService'=>array(

            'class'=>'UserService',

            // Additional config

        ),

    ),



And then call it from anywhere in your application using:




Yii::app()->userService->doSomething();



It’s not as type safe as using type hinting to specify the required interfaces, but it should work quite well within the context of Yii 1.1.x.

OK, forget dependency injection. I want to use interface in my controller and call the interface methods in it, like I explained in my first post. I will have two or more classes that implement that interface, so using multiple classes as components, does not help my issue.

So, how do I use interface in Yii controller?

Thanks,

Andrej

How and when are you deciding which of the concrete classes to use? What are the factors that determine which class is appropriate for the current request?

I’m not sure you understand how interfaces work. One good answer I found is this: http://stackoverflow.com/questions/8552505/when-to-use-interfaces-in-php/8552532

The whole point of using interfaces is that when you use in your controller a method that is declared in the interface, you don’t care (at the moment) about the class that implements it.

I do understand how interfaces work, but at some point, you have to specify a concrete class (such as the one you want to pass into the controller).

I was trying to determine when you wish to make this choice and which factors influence the choice.

I don’t have to specify any class, that is the point of using an interface. I want to pass the interface in the controller, so I can use the methods that are defined in that interface (the body of those function will be in various classes that implement that interface).

I’m going to stop responding after this post because we’re going around in circles, but I’ll attempt to reiterate one more time…

At some point in your code, you’ll need to specify which of your concrete classes will be used to provide the functionality behind your interface methods. I was trying to determine when and how this decision is made so I could suggest a suitable place in Yii to provide access to the class.

That aside, if you’re looking for a framework comparable to .Net MVC, you might want to check out one of the more enterprise targeted frameworks, such as Symphony or Zend. These have features like dependency injection built in.

EDIT:

I also found this thread, which may help.

Thanks, I’ll take a look at it!