Container
Container implementation which follow PSR-11.
Requirements
PHP | VERSION | Container Version |
---|---|---|
8.0 < | <= 1.6 | 1.0 |
>= 8.0 | >= 1.7 | 1.0 |
>= 8.0 | >= 1.8 | 2.0 |
Installation
composer require gravatalonga/container
Usage
Basic Usage
use Gravatalonga\Container\Container;
$container = new Container();
$container->set('random', function() {
return rand(0, 1000);
});
$container->share('uniqueSeed', function() {
return rand(0, 1000);
});
// create alias 'sessionId'
$container->alias('uniqueSeed', 'sessionId');
echo $container->get('random'); // get random number each time you call this.
if ($container->has('uniqueSeed')) {
echo $container->get('uniqueSeed'); // get same random number.
}
When creating a new instance of Container, you can pass on first argument configurations or entries to be already bonded into container.
use Gravatalonga\Container\Container;
new Container([
'settings' => ['my-settings'],
FooBar::class => function (\Psr\Container\ContainerInterface $c) {
return new FooBar();
}
]);
Using Service Provider
use Gravatalonga\Container\Container;
$container = new Container();
$container->set(RedisClass::class, function () {
return new RedisClass();
});
// then you can use...
$cache = $container->get('Cache');
When using set
, factory
or share
with Closure and if you want to get Container
it's self, you can pass type hint of ContainerInterface
as argument.
use Gravatalonga\Container\Container;
use Psr\Container\ContainerInterface;
$container = new Container([
'server' => 'localhost',
'username' => 'root'
]);
$container->set('Cache', function (ContainerInterface $container) {
// some where you have binding this RedisClass into container...
return $container->make(RedisClass::class, [
'server' => $container->get('server'),
'username' => $container->get('username')
]);
});
// set is a method alias of factory
$container->factory('CacheManager', function() {
return new CacheManager();
});
// then you can use...
$cache = $container->get('Cache');
Using Array like access
use Gravatalonga\Container\Container;
$container = new Container();
$container[FooBar::class] = function(ContainerInterface $container) {
return new FooBar($container->get('settings'));
};
if (isset($container[FooBar::class])) {
echo $container[FooBar::class]->helloWorld();
}
Alias
Alias like the name show, it to make a possibility to make an alias from one entry to another. It will throw an exception if can't be found.
use Gravatalonga\Container\Container;
$container = new Container();
$container->set('settings', ['driver' => 'default']);
$container->set(FooBar::class, function($settings) {
return new FooBar($settings);
});
$container->alias(FooBar::class, 'foo.bar');
$foobar = $container->get('foo.bar');
Callable as alternative
use Gravatalonga\Container\Container;
$class = new class
{
public function get(): int
{
return mt_rand(0, 100);
}
};
$container = new Container();
$container->factory('random', [$class, 'get']);
$foobar = $container->get('random'); // it will get random int
Extend
In order implementation to be ease for other services providers extend
method was created.
use Gravatalonga\Container\Container;
class Test
{
/**
* @var string
*/
public $name;
public function __construct($name = 'Jonathan Fontes')
{
$this->name = $name;
}
}
$container = new Container();
$container->get(Test::class, function(ContainerInterface $container) {
return new Test;
});
$container->extend(Test::class, function(ContainerInterface $container, $test) {
return new Test($test->name.' - The greatest!');
});
echo $container->get(Test::class); // It will print 'Jonathan Fontes - The greatest!';
Advance usage
Container is capable to resolve class who isn't bounded, it will resolve dependencies from __construct
type-hint/built-in which is bounded. Read example code below:
Information: built-in is type which is built in on PHP, which is
string
,int
,boolean
, etc. Type Hint is type which is created by user land, such as, when creating a class you are creating a new type.
Using Type Hint Class
use Gravatalonga\Container\Container;
class FooBar {}
class Test
{
public function __construct(FooBar $foobar)
{
$this->foobar = $foobar;
}
}
$container = new Container();
$container->set(FooBar::class, function () {
return new FooBar();
});
$container->get(Test::class); // FooBar it will inject into Test class.
Note: We only support resolving auto wiring argument on construction if they are bounded into container. Otherwise it will throw an exception if can't find entry.
Using Built in type
use Gravatalonga\Container\Container;
class Test
{
public function __construct(string $name)
{
$this->name = $name;
}
}
$container = new Container();
$container->set('name', 'my-var');
$container->get(Test::class); // my-var it will inject into Test class.
If argument accept nullable if can't be resolve it will pass default value which in this case is null
.
use Gravatalonga\Container\Container;
class Test
{
/**
* @var string
*/
private $name;
public function __construct(string $name = null)
{
$this->name = $name;
}
}
$container = new Container();
$container->get(Test::class); // null it will inject into Test class.
In also attempt to resolve auto wiring of construction by its default value, it will check default value of __construct
and it will pass that default value.
First case, if value is a simple built-in type value.
use Gravatalonga\Container\Container;
class Test
{
/**
* @var string
*/
private $name;
public function __construct($name = 'Jonathan Fontes')
{
$this->name = $name;
}
}
$container = new Container();
$container->get(Test::class); // 'Jonathan Fontes' it will pass into container...
Tip
It's well-known that using singleton pattern, it's an anti-pattern. But small feature can't hurt you
So, you can use:
$container = new Container();
// ...
Container::setInstance($container);
Then you can get instance of container,
$container = Container::getInstance();
Tips: The container can detected circular dependencies.
Change log
Please see CHANGELOG for more information on what has changed recently.
Testing
composer grumphp
Contributing
Please see CONTRIBUTING and CODE_OF_CONDUCT for details.
Security
If you discover any security related issues, please email jonathan.alexey16[at]gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.