php – 是依赖注入,这是不好的做法吗?

我有一个小框架,我这样编码.我不知道它是否被称为依赖注入.我不知道它是否像一个设计模式.我也不知道,想知道如果通过$这是param是一个糟糕的做法.

看看这个; (不是一个工作的例子,只是将这些代码写入浏览器进行说明.)

/* This is engine model */
require_once('Database.class.PHP');
require_once('Image.class.PHP');
require_once('Misc.class.PHP');
require_once('BBCode.class.PHP');

class FrameWork_Engine_Model
{
    public $database,$config,$misc,$bbcode,$controller,$image;

    function __construct($config)
    {
            $this->database = new Database($configParams);
            $this->image = new Image($this);
            $this->misc = new Misc($this);
            $this->bbcode = new BBCode($this);
            $this->controller = new Controller($this); //here I call Register controller depending on routing,in this case,register controller.
    }
 ...
 }
/* This is register controller */
 class Register extends Base_Controller
 {
       /*I can access anything over Engine Model in my controllers */
       $this->engine->database->query(); //I access database model
       $this->engine->bbcode->tag('you'); //I access bbcode model
       $this->engine->image->sanitizeUploadedFile(); //I access image model

       //etc. I can access others models like this.
 }

基本上,我的控制器可以通过引擎模型访问任何型号.我认为依赖注入是关于将依赖关系注入控制器?像我的注册控制器需要一个数据库模型,路由模型和模板模型工作.这里有它所依赖的一切.我错了吗

有了这些话,我的问题是:

>这是一个有效的依赖注入示例吗?如果不是,那是什么?它有设计模式的名称吗?
>如果与依赖注入无关,DI需要做哪些改变?
在新创建的类上传递$this参数是不好的做法?如果是,为什么?

PS.我知道问题中的3个问题不是stackoverflow喜欢的东西,但是我不想复制粘贴整个文本来询问它们.

你几乎在那里

问题1

不,我不认为它是一个有效的依赖注入示例.它类似于一个服务定位器(因为您正在将整个容器注入到您的服务中并使用它来“定位”依赖服务).

问题2

你在依赖注入和依赖注入容器之间造成一个小的混乱.

首先,依赖注入意味着在运行时将依赖关系推送到对象中,而不是创建/拉取它们.

举例说明:

//hardcoded dependecies
class BadService
{
    public function __construct() 
    {
        $this->dep1 = new ConcreteObject1();
        $this->dep2 = new ConcreteObject2();
    }
}

所以在上面的例子中,BadService使它在运行时连接其他依赖项是不可能的,因为它们已经很难被拖入构造函数本身.

//service locator pattern
class AlmostGoodService
{
    public function __construct(Container $container)
    {
        $this->dep1 = $container->getADep1();
        $this->dep2 = $container->getADep2();
    }
}

在AlmostGoodService示例中,我们已经从前面的示例中删除了硬依赖关系,但是我们仍然依赖于容器的特定实现(这意味着我们的服务不可重用,而不提供该容器的实现).这是与您正在做的事情相匹配的示例.

//dependecy injection    
class GoodService
{
    public function __construct($dep1,OptionalInterface $dep2)
    {
        $this->dep1 = $dep1;
        $this->dep2 = $dep2;
    }
}

GoodService服务不关心创建它的具体依赖关系,并且可以在运行时轻松地“有线”地执行$dep1或$dep2的OptionalInterface的“协议”的任何依赖关系(因此名称Inversion of Control – 依赖注入背后的基本概念).

执行此接线的组件称为dependency injection container.

现在,dependency injection container是最简单的形式,只不过是一种能够在运行时基于某种形式配置对象的对象.

我说你几乎在那里,但你的实现有一些问题:

>接线应该是懒惰的(你不想让所有的工作在你的构造函数中,因为你的应用程序会随着增长而大大减慢)
>你不应该将整个容器($this)作为一个依赖关系,因为你会回到一个较弱的inversion of control,即service locator.你应该把具体的依赖关系传递给你的服务构造函数

问题3

有些情况下,您会发现自己想要将整个$container作为依赖关系传递给服务(即控制器或懒惰服务工厂),但一般来说,远离这种做法会更好,因为它将使您的服务更可重复使用和更容易测试.当您感觉到您的服务具有太多的依赖关系时,那么这是一个很好的迹象,即您的服务太多,这是分割它的好时机.

原型容器实现

所以,根据上面的答案,这里是一个修改(远非完美)的实现:

/* This is the revised engine model */
class FrameWork_Engine_Model
{
    function __construct($config)
    {
            $this->config = $cofig; 
    }

    public function database()
    {
        require_once('Database.class.PHP');
        return new Database($this->config['configParams']);
    }

    public function bbcode()
    {
        require_once('BBCode.class.PHP');
        return new BBCode($this->database());
    }

    public function image()
    {
        require_once('Image.class.PHP');
        $this->image = new Image($this->config['extensionName']);
    }
    ....

    public function register_controller($shared = true)
    {
        if ($shared && $this->register_controller) {
          return $this->register_controller;
        }

        return $this->register_controller = new Register_Controller($this->database(),$thus->image(),$this->bbcode());
    }
 }

现在,要使用你的服务:

$container = new FrameWork_Engine_Model(); 
$container->register_controller()->doSomeAction()

可以改进什么?您的容器应该:

>提供一种分享服务的方式 – 也就是仅将其初始化一次
> lockable – 提供一种在配置后锁定它的方法
>能够与其他容器“合并” – 这样您的应用程序将真正模块化
>允许optional dependencies
>允许scopes
>支持tagging services

准备使用DI容器实现

所有这些都有关于Dependency Injection的明确文件

> PimplePHP 5.3轻量级DI容器
> Symfony2 DI ContainerPHP 5.3功能完整的DI容器
> Juice DI – 小PHP 5.2 DI容器

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...