【问题标题】:PHP DI/IoC Container configuration for every object in Application or?应用程序中每个对象的 PHP DI/IoC 容器配置还是?
【发布时间】:2015-05-14 07:33:56
【问题描述】:

我有一个问题:我需要为应用程序中的每个对象配置我的 DI/IoC 容器还是只配置工厂?

现在我有这样的东西:

'serviceFactory' => function() use ($container) {
    return new \Application\Core\Factory\ServiceFactory($container->get('entityFactory'), $container->get('repositoryFactory'), $container->get('cache'), $container->get('file'), $container->get('image'));
},

'repositoryFactory' => function() use ($container) {
    return new \Application\Core\Factory\RepositoryFactory($container->get('database'), $container->get('queryBuilder'), $container->get('mapper'), $container->get('language'));
},

'entityFactory' => function() use ($container) {
    return new \Application\Core\Factory\EntityFactory($container->get('language'));
},

然后,应用程序将不必要的对象加载到其他不需要的对象中。

示例:在 BlogService 中,我不使用 File 类或 Image 类。在 ThumbnailService 中我这样做了,但我没有在其中使用 EntityRepository

那么,我是否需要在我的 DI/IoC 容器中导入一些延迟加载,或者我需要像这样编写每个实体/存储库/服务/控制器连接:

'blogController' => function() use ($container) {
    return new \Application\Controller\BlogController($container->get('blogService'));
},

'blogService' => function() use ($container) {
    return new \Application\Service\BlogService($container->get('blog'), $container->get('categoryEntity'), $container->get('blogRepository'), $container->get('cache'));
},

'blogRepository' => function() use ($container) {
    return new \Application\Model\Repository\BlogRepository($container->get('database'), $container->get('queryBuilder'), $container->get('mapper'), $container->get('language'));
},

'blog' => function() use ($container) {
    return new \Application\Model\Entity\Blog($container->get('language'));
},

'thumbnailService' => function() use ($container) {
    return new \Application\Service\ThumbnailService($container->get('image'), $container->get('file'));
},

但这样我可能会编写所有 50-100 个实体、存储库、服务和控制器,可能会过度优化?

有什么建议吗?

【问题讨论】:

    标签: php dependency-injection ioc-container


    【解决方案1】:

    不,通常您只需要注册可以变化的类型,即抽象的具体实现。如果你不使用抽象,那么 DI 容器就没那么有用了。

    DI 容器应允许使用约定注册类型,例如将“服务”中所需名称的所有类注册为服务。这样,您只需定义一些“规则”,无论您在应用程序中有多少服务,注册都会自动完成。至少 .net 中的情况是这样的,但显然手动编写 50-100 个类的注册是一种代码味道。

    更新

    应该是这样的

     interface ISomeService {}
    
     class MyService implements ISomeService { }
    
     class OtherService
     {
         private $svc;
         function __construct(ISomeService $svc)
         {
             $this->svc=$svc;
         }
    
          function doStuff()
          {
              //do stuff using  $this->svc
          }
     }
    
     //DiContainer
     //here you you should register things (I don't know a container for php, I'll write what I'm using in C#, but you'll get the idea)
                 container.RegisterTypes(myAssembly)
                .Where(type=>type.Name.EndsWith("Service"))
                .AsSelf()
                .AsImplementedInterfaces();
    

    上面的代码告诉容器扫描所有名称以“Service”结尾的类(我的约定),并自动注册它们以在请求特定类型或由该特定类型实现的接口实现时使用输入。

    在我们的示例中,这意味着当容器请求 OtherService 的实例时,容器知道使用 MyService 类型作为 的具体类型ISomeService 。容器会查看您的构造函数以检测对象需要哪些依赖项。

    为了正确使用 DI 容器,您的 (mvc) 框架应该了解它,因为它并不打算由您的应用直接使用。在某些情况下,服务定位器模式是有效的,但通常框架应该使用容器来创建您需要的服务的实例

    您在应用程序启动时配置容器(作为 mvc 框架的一部分或与您的 mvc 框架集成),仅此而已。接下来,您只需定义接口和类(服务、存储库、事件处理程序等)。您唯一应该做的就是提出一些约定,以允许您的容器根据它们自动注册类(例如将您的服务命名为“服务”)。

    DI 容器首先出现在静态类型语言(java、C#)中,与不受类型约束的动态语言相比,使用它更有意义(这就是我在 php 中使用类型提示的原因)。它们仍然有用,但有点难以理解。

    【讨论】:

    • 嗯,您的意思是如果我需要注入 ThumbnailService,它会自动检测并包含 File 和 Image 类,如果不是(否则)则包含 Repository、Entity... 现在,我正在使用这样的容器:@987654323 @,但也许我可以使用 $container->get('Service', 'Thumbnail'); 之类的东西,然后它会检测要包含的内容和不包含的内容...
    • 感谢示例和提示(“容器查看您的构造函数以检测对象需要哪些依赖项。”)发现了一些有趣的东西,我认为这可能是解决方案 - stackoverflow.com/questions/4262350/…
    • 还有一个问题,你说框架应该知道 DI Container,但是怎么做呢?我有路由器和调度程序。路由器检查当前活动的 url,对其进行解析,并找出应该包含哪个控制器和带有参数的操作(方法)。然后我启动 Dispatcher 来分派那个控制器。我应该将 DI Container 注入 Dispatcher 以便它可以动态加载 Controller => Service => Repository 还是?
    • IMO 你应该使用一个了解 DI 容器的框架,比如 Laravel,而不是构建/修改你自己的
    • 我正在创建自己的学习框架。将研究 Laravel,看看他们是如何解决这个问题的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2013-02-09
    • 2011-02-09
    • 1970-01-01
    相关资源
    最近更新 更多