Skip to content

Commit 0a5ae38

Browse files
committed
Release 0.1
0 parents  commit 0a5ae38

File tree

9 files changed

+279
-0
lines changed

9 files changed

+279
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
.phpunit.result.cache

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
>**:heavy_exclamation_mark: Basic container implementation with the ability to inject dependencies**
2+
3+
### Requirements
4+
5+
PHP >= 8.0.0
6+
7+
### How to use the library
8+
9+
Add the latest version of MicroDependencyInjection into your project by using Composer or manually:
10+
11+
__Using Composer (Recommended)__
12+
13+
Either run the following command in the root directory of your project:
14+
```
15+
composer require micro/dependency-injection
16+
```
17+
18+
Or require the Checkout.com package inside the composer.json of your project:
19+
```
20+
"require": {
21+
"php": ">=8.0",
22+
"micro/dependency-injection": "dev-master"
23+
},
24+
```
25+
26+
### Example
27+
28+
After adding the library to your project, include the file autoload.php found in root of the library.
29+
```html
30+
include 'vendor/autoload.php';
31+
```
32+
33+
Simple usage:
34+
```php
35+
use \Micro\Component\DependencyInjection\Container;
36+
37+
class Logger {
38+
}
39+
40+
class Mailer {
41+
public function __construct(private Logger $logger) {}
42+
}
43+
44+
$container = new Container();
45+
46+
$container->register(Logger::class, function(Container $container) {
47+
return new Logger();
48+
});
49+
50+
$container->register(Mailer::class, function(Container $container) {
51+
return new Mailer($container->get(Logger::class));
52+
});
53+
54+
$mailer = $container->get(Mailer::class);
55+
```
56+
57+
### Sample code for:
58+
59+
- [PSR-11](https://www.php-fig.org/psr/psr-11/)

composer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "micro/dependency-injection",
3+
"description": "Dependency injection service container",
4+
"type": "library",
5+
"license": "MIT",
6+
"version": "0.1",
7+
"autoload": {
8+
"psr-4": {
9+
"Micro\\Component\\DependencyInjection\\": "src/"
10+
}
11+
},
12+
"authors": [
13+
{
14+
"name": "Stanislau.Komar",
15+
"email": "stanislau_komar@epam.com"
16+
}
17+
],
18+
"minimum-stability": "stable",
19+
"require": {
20+
"psr/container": "^2.0"
21+
},
22+
"require-dev": {
23+
"phpunit/phpunit": "^9"
24+
}
25+
}

phpunit.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
backupGlobals="false"
6+
backupStaticAttributes="false"
7+
colors="true"
8+
convertErrorsToExceptions="true"
9+
convertNoticesToExceptions="true"
10+
convertWarningsToExceptions="true"
11+
processIsolation="false"
12+
stopOnFailure="false">
13+
<coverage>
14+
<include>
15+
<directory suffix=".php">src/</directory>
16+
</include>
17+
</coverage>
18+
<testsuites>
19+
<testsuite name="Micro Component: Dependency Injection Unit Test Suite">
20+
<directory>tests/unit</directory>
21+
</testsuite>
22+
</testsuites>
23+
<php>
24+
<env name="APP_ENV" value="testing"/>
25+
</php>
26+
</phpunit>

src/Container.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection;
4+
5+
6+
use Micro\Component\DependencyInjection\Exception\ServiceNotRegisteredException;
7+
use Micro\Component\DependencyInjection\Exception\ServiceRegistrationException;
8+
use Psr\Container\ContainerInterface;
9+
use \Closure;
10+
11+
class Container implements ContainerInterface, ContainerRegistryInterface
12+
{
13+
/**
14+
* @var array<string, object>
15+
*/
16+
private array $services;
17+
18+
/**
19+
* @var array<string, Closure>
20+
*/
21+
private array $servicesRaw;
22+
23+
24+
public function __construct()
25+
{
26+
$this->services = [];
27+
$this->servicesRaw = [];
28+
}
29+
30+
/**
31+
* {@inheritDoc}
32+
*/
33+
public function get(string $id)
34+
{
35+
return $this->lookupService($id);
36+
}
37+
38+
/**
39+
* {@inheritDoc}
40+
*/
41+
public function has(string $id): bool
42+
{
43+
return !empty($this->servicesRaw[$id]) || !empty($this->services[$id]);
44+
}
45+
46+
/**
47+
* {@inheritDoc}
48+
*/
49+
public function register(string $id, \Closure $service): void
50+
{
51+
if($this->has($id)) {
52+
throw new ServiceRegistrationException($id);
53+
}
54+
55+
$this->servicesRaw[$id] = $service;
56+
}
57+
58+
/**
59+
* @param string $id
60+
* @return object
61+
*/
62+
private function lookupService(string $id): object
63+
{
64+
if(!empty($this->services[$id])) {
65+
return $this->services[$id];
66+
}
67+
68+
return $this->createServiceInstance($id);
69+
}
70+
71+
/**
72+
* @param string $id
73+
* @return object
74+
*/
75+
private function createServiceInstance(string $id): object
76+
{
77+
if(empty($this->servicesRaw[$id])) {
78+
throw new ServiceNotRegisteredException($id);
79+
}
80+
81+
$raw = $this->servicesRaw[$id];
82+
$service = $raw($this);
83+
84+
$this->services[$id] = $service;
85+
86+
return $service;
87+
}
88+
}

src/ContainerRegistryInterface.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection;
4+
5+
6+
interface ContainerRegistryInterface
7+
{
8+
/**
9+
* @param string $alias
10+
* @param \Closure $service
11+
* @return void
12+
*/
13+
public function register(string $id, \Closure $service): void;
14+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection\Exception;
4+
5+
use Psr\Container\NotFoundExceptionInterface;
6+
7+
class ServiceNotRegisteredException extends \RuntimeException implements NotFoundExceptionInterface
8+
{
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection\Exception;
4+
5+
use Psr\Container\ContainerExceptionInterface;
6+
7+
class ServiceRegistrationException extends \RuntimeException implements ContainerExceptionInterface
8+
{
9+
10+
}

tests/unit/ContainerTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Micro\Component\DependencyInjection\Tests;
4+
5+
use Micro\Component\DependencyInjection\Container;
6+
use Micro\Component\DependencyInjection\Exception\ServiceNotRegisteredException;
7+
use Micro\Component\DependencyInjection\Exception\ServiceRegistrationException;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class ContainerTest extends TestCase
11+
{
12+
public function testContainerResolveDependencies(): void
13+
{
14+
$container = new Container();
15+
16+
$container->register('test', function ( Container $container ) { return new class {
17+
public string $name = 'success';
18+
}; });
19+
20+
$service = $container->get('test');
21+
$this->assertIsObject($service);
22+
$this->assertEquals('success', $service->name);
23+
}
24+
25+
public function testRegisterTwoServicesWithEqualAliasesException(): void
26+
{
27+
$this->expectException(ServiceRegistrationException::class);
28+
$container = new Container();
29+
30+
$container->register('test', function ( Container $container ) { return new class {}; });
31+
$container->register('test', function ( Container $container ) { return new class {}; });
32+
}
33+
34+
public function testContainerUnresolvedException(): void
35+
{
36+
$this->expectException(ServiceNotRegisteredException::class);
37+
38+
$container = new Container();
39+
$container->register('test', function ( Container $container ) { return new class {
40+
public string $name = 'success';
41+
}; });
42+
43+
$container->get('test2');
44+
}
45+
}

0 commit comments

Comments
 (0)