PHP code example of grithin / ioc-di

1. Go to this page and download the library: Download grithin/ioc-di library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

grithin / ioc-di example snippets


# HEADER #
use \Grithin\{ServiceLocator, DependencyInjector};
use \Grithin\IoC\{NotFound, ContainerException, MissingParam, Datum, Service, Call, Factory};

$sl = new ServiceLocator;
$di = $sl->injector();


## INSERT HEADER ##

class Creature{
	public $name;
	public function __construct(NameInterface $name){
		$this->name = $name;
	}
}
interface NameInterface{ }
class Name implements NameInterface{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}

$sl = new ServiceLocator;
$di = $sl->injector();

# add "Name" into services
$sl->bind('Name');

# construct "Creature" with injected Name instance
$bob = $di->call('Creature');
echo $bob->name->text;
#> 'bob'

## INSERT HEADER ##

class Creature{
	public $name;
	public $age;
	public function __construct(Name $name, Age $age){
		$this->name = $name;
		$this->age = $age;
	}
}
class Name{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}
class Age{
	public $text;
	public function __construct($text='20'){
		$this->text = $text;
	}
}


# add "Age" into services
$sl->bind('Age');

# pass in the $age parameter by matching the parameter name
$bob = $di->call_with('Creature', ['age'=> new Age('30')]);
echo $bob->age->text;
#> 30

# pass in the $age parameter by matching the position
$bob = $di->call_with('Creature', [1=> new Age('30')]);
echo $bob->age->text;
#> 30

## INSERT HEADER ##

class Creature{
	public $name;
	public function __construct(NameInterface $name){
		$this->name = $name;
	}
}
interface NameInterface{ }
class Name implements NameInterface{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}


# use a default for the "name" parameter
$bob = $di->call('Creature', ['defaults'=>['name'=> new Name('Sue')]]);
# since "Name" has not been registered as a service, ServiceLocator will fail to find it, and use the default provided
echo $bob->name->text;
#> sue

## INSERT HEADER ##

interface NameInterface{}
class Name implements NameInterface
{
	public $text;
	public function __construct($text = 'bob')
	{
		$this->text = $text;
	}
}
function sayName(NameInterface $name){
	echo $name->text;
}

# create a service with pre-set construction options
$name_service = new Service(Name::class, ['with'=>['text'=>'sue']]);

# injector will fall back on the default, $name_service, since no NameInterface is registered
$di->call('sayName', ['defaults'=> ['name'=>$name_service]]);
#> sue

## INSERT HEADER ##

class Person{
	public $name;
	function __construct($name){
		$this->name = $name;
	}
	function sayName(){
		echo $this->name;
	}
}


# Bind service id Person to the Person class, with constructor parameter using Datum "name"
$sl->bind('Person', Person::class,  ['with'=>['name'=>new Datum('name')]]);

# define the Datum for the DataLocator
# this is one benefit to using Datum - it can be defined after a service is bound to use it
$sl->data_locator->set('name', 'sue');

function sayName(Person $person){
	return $person->sayName();
}

# getName will cause ServiceLocator to create Person instance, which causes DataLocator to pull "name"
$di->call('sayName');
#> sue

# change Datum resolution
$sl->data_locator->set('name', 'bob');

# a new Person instance will be made, and Datum "name" will now resolve to "bob"
$di->call('sayName');
#> bob

## INSERT HEADER ##

class Person{
	public $name;
	function __construct($name){
		$this->name = $name;
	}
	function sayName(){
		echo $this->name;
	}
}


function getName() {
	return 'bob';
}

# Invoke getName when instantiating "Person" for parameter $name
$sl->bind('Person', Person::class,  ['with'=>['name'=>new Call('getName')]]);

function sayName(Person $person){
	return $person->sayName();
}

$di->call('sayName');
#> bob

## INSERT HEADER ##

$random = function(){ return rand(0,20000); };
$sl->data_locator->set('rand', new Call($random));
echo $sl->data_locator->get('rand');
#> 1231

# the DataLocator only runs the callable once, so it will return the same value here
echo $sl->data_locator->get('rand');
#> 1231

# a factory can be used to get new data every time
$sl->data_locator->set('rand', new Factory($random));

echo '|';
echo $sl->data_locator->get('rand');
echo '|';
#> 3421
echo $sl->data_locator->get('rand');
#> 8291

## INSERT HEADER ##

$sl->data_locator->set('Server', 'localhost');

function printServer($Server){
	echo $Server;
}

$bob = $di->call('printServer');
#> localhost

## INSERT HEADER ##
class Database{
	function __construct(){
		echo 'connecting... ';
		# ... expensive connection stuff ...
	}
	function query(){
		return 'bob';
	}
}

$sl->singleton('Database');

function getUserName(Database $db){
	echo $db->query();
}

$di->call('getUserName');
#> connecting... bob
$di->call('getUserName');
#> bob

## INSERT HEADER ##
class Database{
	public $host;
	function __construct($host = 'local_899') {
		$this->host = $host;
	}
}

function getDb(Database $db){
	echo $db->host;
}

# Can use the `Service` class to override service config
$config = ['i'=>0];
$sl->singleton('Database', new Database('remote'));
$di->call('getDb');
#> remote

## INSERT HEADER ##
interface DatabaseInterface {}
class Database implements DatabaseInterface{
	function query(){
		return 'bob';
	}
}

$sl->bind('DatabaseInterface', 'LinkMiddleMan');
$sl->bind('LinkMiddleMan', 'Database');


function getUserName(DatabaseInterface $db){
	echo $db->query();
}

# ServiceLocator will resolve DatabaseInterface to LinkMiddleMan, and then LinkMiddleMan to Database
$di->call('getUserName');
#> bob


## INSERT HEADER ##

class Database{
	function query(){
		return 'bob';
	}
}
function getDatabase(){
	return new Database;
}

function getUserName(Database $db){
	echo $db->query();
}


# Using the `Call` class
$sl->bind('Database', new Call('getDatabase'));
$di->call('getUserName');
#> bob

# Using a closure
$sl->bind('Database', function(){ return getDatabase(); });
$di->call('getUserName');
#> bob

interface DatabaseInterface {}
class Database implements DatabaseInterface {
	public $host;
	function __construct($host='local_899'){
		$this->host = $host;
	}
}

function getDb(DatabaseInterface $db){
	echo $db->host;
}


# Can use the `Service` class to override service config
$sl->bind('Database');
$sl->bind('DatabaseInterface', new Service('Database', ['with'=>['host'=>'remote_123']]));
$di->call('getDb');
#> remote_123


# basic
$sl->data_locator->set('x', '123');

# lazy loaded (called once)
$sl->data_locator->set('y', function(){ return '456'; });
function return_456(){
	return '456'
}
$sl->data_locator->set('y', new Call('return_456'));

# factory (called every time)
$sl->data_locator->set('y', new Factory('return_456'));

$sl = new ServiceLocator(['check_all'=>true]);