如何全局访问依赖项注入容器


How to access dependency injection container globally

我正在用PHP构建自己的小型MVC框架,只是为了学习和更好地理解。

我用路由器创建了一个小框架。

在我的索引中.php我为我的应用程序创建了一个容器。

索引.php

use 'Oak'Route'Route as Route;
use 'Oak'Route'Routes as Routes;
use 'Oak'App'App as App;
$routes = new Routes();
$routes->addRoute(new Route('home', 'index', 'index'));
$routes->addRoute(new Route('user/{username}/{id}', 'index', 'about'));
$routes->addRoute(new Route('help', 'help', 'index'));
$container = new Container();
$container->set('app', function() use ($routes) {
    return new App($routes, new 'Oak'Header'Request());
});
$app = $container->get('app');
$app->run();

Container.php

& ContainerInterface.php

interface ContainerInterface {
public function set($name, $service);
public function get($name, array $params = array());
public function has($name);
public function remove($name);
public function clear();
}
class Container implements ContainerInterface {
    protected $services = array();
    public function set($name, $service) {
        if(!is_object($service)) {
            throw new InvalidArgumentException("Only objects can be registred");
        }
        if(!in_array($service, $this->services, true)) {
            $this->services[$name] = $service;
        }
        return $this;
    }
    public function get($name, array $params = array()) {
        if(!isset($this->services[$name])) {
            throw new RuntimeException($name ." has not been registred in the container");
        }
        $service = $this->services[$name];
        return !$service instanceof Closure ? $service : call_user_func_array($service, $params);
    }
    public function has($name):bool {
        return isset($this->services[$name]);
    }
    public function remove($name) {
        if(isset($this->services[$name])) {
            unset($this->services[$name]);
        }
        return $this;
    }
    public function clear() {
        $this->services = array();
    }
    public  function getServices():array {
        return $this->services;
    }
}

我现在的问题是如何从我的控制器、我的应用程序文件等启用对容器的访问。一种解决方案是在容器中使用单例或静态方法?

我已经阅读了很多关于该主题的博客文章和文章,但我似乎所有示例都只与索引文件中的容器通信?

我也开始尝试继承,该应用程序扩展了容器,然后将其传递给控制器?

我的问题是,如果这是要走的路,您如何从应用程序中的任何位置启用对容器的访问?

查看 Singleton 设计模式.. 你需要这样的东西:

class Container {
    private static $instance;
    //prevent from creating a container class by itself
    private function __construct() {};    
    /* .... */
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new Container();
        }
    }
}

然后在代码中的任何地方使用而不是使用$container = new Container();使用$container = Container::getInstance();

无论如何,我强烈建议您签出 Pimple (http://pimple.sensiolabs.org/),这是非常好的代码,具有延迟加载。写出像 Pimple 这样优秀且功能丰富的东西需要花费大量时间。