StaticAccessTrait   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 16
dl 0
loc 81
rs 10
c 2
b 0
f 1
wmc 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A setContainer() 0 3 1
A __callStatic() 0 11 4
A getContainer() 0 7 2
A create() 0 4 1
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Di
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Di\Util;
13
14
use Phoole\Di\Container;
15
use Phoole\Di\Exception\LogicException;
16
use Phoole\Di\Exception\RuntimeException;
17
use Psr\Container\NotFoundExceptionInterface;
18
use Phoole\Di\Exception\UnresolvedClassException;
19
20
/**
21
 * StaticAccessTrait
22
 *
23
 * Static facade extension
24
 *
25
 * ```php
26
 * // accesss predefined service
27
 * $cache = Container::cache();
28
 *
29
 * // create an object whose dependencies will be injected automatically
30
 * $obj = Container::create(MyClass::class);
31
 * ```
32
 *
33
 * @package Phoole\Di
34
 */
35
trait StaticAccessTrait
36
{
37
    /**
38
     * @var Container[]
39
     */
40
    protected static $containers = [];
41
42
    /**
43
     * Initiate an object with its dependencies injected automatically
44
     *
45
     * - dependency in constructor is resolved automatically
46
     * - 'di.before' & 'di.after' methods executed on this object
47
     *
48
     * ```php
49
     * // with all dependencies injected already
50
     * $myObj = Container::create(MyClass::class);
51
     * ```
52
     *
53
     * @param  string|callable|object $className  object or classname
54
     * @param  array                  $arguments  constructor arguments if any
55
     * @return object
56
     */
57
    public static function create($className, array $arguments = []): object
58
    {
59
        return self::getContainer()->newInstance(
60
            ['class' => $className, 'args' => $arguments]
61
        );
62
    }
63
64
    /**
65
     * Get service object (predefined) by its id in a STATIC way
66
     *
67
     * ```php
68
     * $cache = Container::cache();
69
     * $logger = Container::logger();
70
     *
71
     * // invokable way, get a mysql db connection
72
     * $db = Container::db('mysql');
73
     * ```
74
     *
75
     * @param  string $name       service id
76
     * @param  array  $arguments  if object is an invokable
77
     * @return object
78
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
79
     * @throws LogicException              if container not instantiated
80
     * @throws UnresolvedClassException    if parameters not resolved
81
     * @throws RuntimeException            if invokable goes wrong
82
     */
83
    public static function __callStatic($name, $arguments): object
84
    {
85
        $object = self::getContainer()->get($name);
86
        try {
87
            // invokable object
88
            if (!empty($arguments) && is_callable($object)) {
89
                return $object($arguments);
90
            }
91
            return $object;
92
        } catch (\Throwable $e) {
93
            throw new RuntimeException($e->getMessage());
94
        }
95
    }
96
97
    /**
98
     * @return Container
99
     * @throws LogicException     if container not instantiated
100
     */
101
    protected static function getContainer(): Container
102
    {
103
        $containerClass = get_called_class();
104
        if (!isset(self::$containers[$containerClass])) {
105
            throw new LogicException("unInitialized container $containerClass");
106
        }
107
        return self::$containers[$containerClass];
108
    }
109
110
    /**
111
     * @param  Container $container
112
     */
113
    protected static function setContainer(Container $container)
114
    {
115
        self::$containers[get_class($container)] = $container;
116
    }
117
}