Cygnite - A Modern Toolkit For Web Developers

The Elegant Way of Building Full-Featured Web Applications

Cygnite Dynamic Routing

IoC Container

Documentation

IoC Container


Introduction

Cygnite has powerful dependency injection container to resolve your class dependencies at runtime. Dependency injection is a software design pattern that implements inversion of control IoC). Cygnite IoC Container gives you more flexibility to write powerful, decoupled and large application.

Usage of Container

Dependency Injection

Cygnite Container can resolve dependencies different ways.

1. Autowiring (Automatic Resolution). Constructor Injection.
2. Interface Injection. Binding an Interface with it's implementation class.
3. Property Injection.

Autowiring

Cygnite container has powerful mechanism to resolve all dependencies of the class at run time without any configuration. Container uses PHP Reflection to understand what parameters a constructor needs. Automatic resolution works only with the constructor injection and must be type-hint.
For Example:

 
namespace Apps\Resources\Extensions;

class Foo 
{
    private $bar;

    public function __construct(\Apps\Resources\Extensions\Bar $bar) 
    {
        $this->bar = $bar;
    }
}


Now make the foo instance using application in your controller.


namespace Apps\Controllers;

use Cygnite\Mvc\Controller\AbstractBaseController;

class UserController extends AbstractBaseController
{
   public function __construct() 
   {
       parent::__construct();

       $app = $this->app();
       $this->foo = $app->make('\Apps\Resources\Extensions\Foo');

       //or
       //$this->foo = $app->resolve('apps.resources.extensions.foo');
   }

}

You can see without doing any kind of configuration Container automatically resolves all dependencies of Foo class and injecting Bar class into it.

Type-Hinting Controller

 
 use Cygnite\Foundation\Application;
 use Cygnite\Mvc\Controller\AbstractBaseController;
 use Apps\Resources\Extensions\Api;

 class HomeController extends AbstractBaseController
 {

    private $api;

    public function __construct(Api $api, $type = "service")
    {
       $this->api = $api;
    }

    public function indexAction()
    {
       $this->api->makePayment();

    }
 }

Autowiring works only with the class, however if type of the parameter is Interface then you need to configure to inform Container which Interface implementation should be injected.

Interface Injection

Register an Interface with it's implementation class. This can be done using src/Apps/Configs/definitions/configuration.php configuration file as below.


   'register.alias' => [
        'FooInterface' => 'Apps\Resources\Extensions\Foo'
   ]

and your controller may look like following.


 
 use Cygnite\Foundation\Application;
 use Cygnite\Mvc\Controller\AbstractBaseController;
 use Apps\Resources\Extensions\FooInterface;

 class HomeController extends AbstractBaseController
 {

    private $foo;

    public function __construct(FooInterface $foo)
    {
       $this->foo = $foo;
    }
 }

Since you registered FooInterface to it's implementation class. Cygnite container automatically inject it run time.

Property Injection

Some time over uses of constructor injection may be messy, in that case you may use property injection. You need to configure which instance should be injection into what property of your controller. This can be achieve using src/Apps/Configs/definitions/configuration.php file.
For Example.

   
    return [
        'property.definition' =>  [
            'HomeController' => [
                'service' => 'apps.resources.extensions.api',
            ],
            'ProductController' => [
                'foo' => 'apps.resources.extensions.foo',
            ],
         ],
    ];

Above we have set service object into service property of HomeController, now container is aware about which instance to inject into service property.



 use Cygnite\Mvc\Controller\AbstractBaseController;
 use Apps\Resources\Extensions\Foo;

 class HomeController extends AbstractBaseController
 {

    private $foo;

    // Instance of class \Apps\Resources\Extensions\Service inject here
    private $service;

    public function __construct(Foo $foo)
    {
       $this->foo = $foo;
    }

    public function indexAction()
    {
       // access the service object directly to do some task
       $this->service->makePayment();
    }
 }

Defining a Parameters or Values

Set a parameter or value into Container using instance as array.



   use Cygnite\Container\Container;

   $container = new Container();

   // define some parameters as array 
   $container['foo'] = 'Bar';
   $container['foo_bar'] = 'FooBar';

   OR
  //Define parameter as property
  $container->bar = 'bar';
  $container->baz = new Baz;
  

Accessing Session Instance Into Controller



   $container = $this->get('cygnite.common.session-manager.session');


Creating Service

Service is an object of system, which can be defined by anonymous functions. If you are fond of Pimple syntax then you will also love Cygnite container.



   use Apps\Resources\Extensions\FooBar;
   use Apps\Resources\Extensions\Api;  

   $container['foo'] = 'Foobar';
   $container['bar'] = 'baz';

   $container->general = function ($c) {
       return new FooBar($c['foo']);// Allowing you to refer other service or values
   };

   $container->api = function ($c) {
       return new Api($c['bar'], $c->general);// Allowing you to refer other service or values
   };


If you look at the above example we have stored parameters into the container, as well as stored general service (General object) into container. Now when returning Api service we are able to inject General and other parameters into the Api. You may also notice the Closure has access of container instance inside it.

Extending Service

In the above example we have created service, now you may also want to extend it. To do that simply use extend method.
Have a look at the below example.


  $container['bar'] = 'baz';

  $container->api = function ($c) {
       return new Api();// Allowing you to refer other service or values
   };

  $container['apiKey'] = 'xxxxxxx';

  //Setter Injection and property injection
  $container->api = $container->extend('api', function ($api, $c)
  {
      $api->key = $c['apiKey'];// set key to public property
      $api->setBar($c->bar);

      return $api;
  });
 
  $container->api; //Hold your Api service


Sharing an Object

Binding as shared is almost similar to Singleton pattern, where the first time object is created and return same object for all subsequent call.



 $container->apiGateway = $container->share(function ($c)
 {
     return new ApiGateway($c->api);
 });

 $container->apiGateway ; // Holds singleton object


Creating Singleton Instance



$container->singleton('foobar', function ($c) {
    $config = [];
    return new FooBar($config);
});


Above closure will save the singleton instance into container. But if you just pass class name in singleton method it will return you the singleton instance of the class as below example.



 $foo = $container->singleton('\Apps\Foo');


Setting A Value Into Container



 $container->set('foo', 'bar');


Getting A Value From Container



 $foo = $container->get('foo');
 show($foo);


Checking Value Exists In Container



 if ($container->has('foo')) {
    // 
 }


Returning All Stored Keys From Container



 $container->keys();


Store factory of objects into Container

You also can use the power of SplObjectStorage. Simply get the object of container and attach factory of objects into it.



 $stdClass = new StdClass;
 $general = new General;
 $api = new Api;

 $container->attach($general);
 show($container->contains($api));

 $container->detach($general);

 $general[$api] = "hello";

 
 $container->addAll($general);
 echo $container[$general]."\n";




Follow Us On Facebook Twitter Google+ Linkedin
Released Under The MIT Public License. Copyrights @2012-2017. Powered by- Sanjoy Dey Productions.