Yii Dependency Injection Container

I have create an yii denpendency injection container that base on PHP-DI, you can find more about its informations here php-di.org/

This extension uses PHP-DI 3.5, and its document you can find at: github.com/mnapoli/PHP-DI/tree/3.x/doc

It require PHP 5.3+

How to use?

After download file attach, let extract it into extensions folder of your project, now in the config file, add config for the extension:




'components'=>array(

...

               'di'=>array(

                        'class'=>'ext.di.DIComponent',

                        'configFile'=>'container.php',

                        'cache'=>'ArrayCache',

                        'useReflection'=>true,

                        'useAnnotations'=>true,

                        'definitionsValidation'=>true,

                        'cacheNamespace'=>''

                ),

...



with:

+configFile: a file in protected/config folder which is an PHP array dependency definition, you can see example here: github.com/mnapoli/PHP-DI/blob/3.x/doc/definition.md (PHP array part)

+cache: which case is used, you can pick one of values:


ApcCache

ArrayCache

FilesystemCache

MemcacheCache

MemcachedCache

PhpFileCache

RedisCache

WinCacheCache

XcacheCache

ZendDataCache

see more information here: github.com/mnapoli/PHP-DI/blob/3.x/doc/performances.md

default is ArrayCache, which is well in development enviroment, in product you should not use this cache stategy

+useReflection: default true

+useAnnotations: default true

+definitionsValidation: default true

+cacheNamespace: default "", prefix cache keys

use can see more at: github.com/mnapoli/PHP-DI/blob/3.x/doc/container-configuration.md

Example:

I have 2 models: User and Profile, each user have its profile

I also have 2 service: UserService and ProfileService




interface UserService {

        public function findUser($id);

}






interface ProfileService {

        public function findUserProfile($userId);

}



Now I have 2 implement for above services:

ProfileService implement:




class ProfileServiceImpl implements ProfileService {

        public function findUserProfile($userId) {

                $profile=new Profile;

                $profile->email='test@email.com';

                $profile->birthday='01/01/1990';

                

                return $profile;

        }

}



In UserService implement, i use ProfileService to find profile of the user, so i use di container to inject dependency to UserService:




class UserServiceImpl implements UserService {

        

        /**

         * @Inject

         * @var ProfileService

         */

        private $profileService;

    

        public function findUser($id) {

                $user=new User();

                $user->id=$id;

                $user->name='test user';

                

                $user->profile=  $this->profileService->findUserProfile($id);

                

                return $user;

        }

}



Here I use property injection with annotation(you must config useAnnotations=true, which is default if you not set).

Now how the DI Container know where the implement of ProfileService is? Here I must define a container.php definition file in protected/config/ folder

Here is its content:




return array(

    'UserService'=>array(

        'class'=>'UserServiceImpl'

    ),

    'ProfileService'=>array(

        'class'=>'ProfileServiceImpl'

    )

);



I have let the container know the implements of UserService and ProfileService I would rather use, so the container will use these specific implement class instances to inject into places need them.

You can use annotation or reflection or define dependencies in config file, it up to you.

The in controller I want to use UserService to find User and print its information out.So this is what i do:




class TestInjectionController extends Controller {

    

        /**

         * @Inject

         * @var UserService 

         */

        private $userService;

        

    

        public function actionViewUser($id){

                Yii::app()->di->container->injectOn($this);


                $user=  $this->userService->findUser($id);

                echo 'Id: '.$user->id . '<br>';

                echo 'Name: '.$user->name.'<br>';

                echo 'Email: '.$user->profile->email.'<br>';

                echo 'Birthday: '.$user->profile->birthday.'<br>';

        }

}



Like in UserServiceImpl, I use annotation to inject dependency here.

One more thing i must do is


Yii::app()->di->container->injectOn($this);

You must call this command to inject dependencies into your controller.Why you must do this? Because the DI Container does not create Controller instance, Yii create it, so the container does not know that your controller need dependencies, you must explicit tell it by that command.

All done :). Hope you feel it helpful!