Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在自己的可重用库中提供依赖项注入 背景_Php_Dependency Injection_Composer Php - Fatal编程技术网

Php 在自己的可重用库中提供依赖项注入 背景

Php 在自己的可重用库中提供依赖项注入 背景,php,dependency-injection,composer-php,Php,Dependency Injection,Composer Php,我正在编写一些可重用库,其中包含的类很少。 其中一个需要有依赖关系,因为一些更复杂的逻辑,我想把这个类的责任委托给其他地方(另一个类) 目标 我不想创建一个bundle,例如Symfony bundle,它可以处理依赖项注入,并提供一种简单的方法将其与客户端代码集成。 我的目标是提供可重用和独立于框架的解决方案 补充资料 我正在使用,并且我已经阅读了有关DI容器的信息,如。 有一个PHPDI的应用程序示例,但它不符合我的要求 例子 库代码片段 <?php class W3CAnalyze

我正在编写一些可重用库,其中包含的类很少。 其中一个需要有依赖关系,因为一些更复杂的逻辑,我想把这个类的责任委托给其他地方(另一个类)

目标 我不想创建一个bundle,例如Symfony bundle,它可以处理依赖项注入,并提供一种简单的方法将其与客户端代码集成。 我的目标是提供可重用和独立于框架的解决方案

补充资料 我正在使用,并且我已经阅读了有关DI容器的信息,如。 有一个PHPDI的应用程序示例,但它不符合我的要求

例子 库代码片段

<?php

class W3CAnalyzer implements WebStandardAnalyzer
{
   private $httpClient;

   public function __construct(HttpClient $httpClient)
   {
      $this->httpClient = $httpClient;
   }

   public function analyze(string $url): WC3AnalysisMetaData
   {
      $siteContent = $this->httpClient->getContent($url);

      //further logic there
   }
}
在客户机项目中,程序员将注册
W3CAnalyzer
,以便使用其DI配置将其注入控制器中作为
WebStandardAnalyzer
(如何注入并不重要)

问题 如果我在我的库内部使用一些DI配置和容器,我如何将此配置与客户机代码集成,这样就有可能注册库类,并且它的所有依赖关系都将得到解决? 我还不知道如何在我的库中组织DI(这实际上是问题的第一部分),我想以某种方式使用上面提到的PHPDI库

总而言之,如何在非框架可重用库中组织DI,以便库可以在每个其他项目中使用(无论使用哪个框架),并且它(该库)的依赖关系也将在该项目的运行时得到解决

谢谢大家!

class W3CAnalyzerFactory
{
    public function build()
    {
         $Subject = new W3CAnalyzer(new HttpClient);

         return $Subject
    }
}
以上是我如何利用工厂模式,并取得了巨大成功。如果
new HttpClient
不足以容纳您的代码(也就是说,它也需要构建),请执行以下操作:

class HttpClientFactory
{
    public function build()
    {
         //modify this to actually construct the HttpClient object, with
         //constructor and/or setter injections
         $Subject = new HttpClient();

         return $Subject
    }
}
$WebStandardController = new WebStandardController(
    (new W3CAnalyzerFactory())
    ->build()
);
然后,您的
W3CAnalyzerFactory
将如下所示:

class W3CAnalyzerFactory
{
    public function build()
    {
         $Subject = new W3CAnalyzer(
             (new HttpClientFactory)
             ->build()
         );

         return $Subject
    }
}
然后,使用您的库的用户可以执行以下操作:

class HttpClientFactory
{
    public function build()
    {
         //modify this to actually construct the HttpClient object, with
         //constructor and/or setter injections
         $Subject = new HttpClient();

         return $Subject
    }
}
$WebStandardController = new WebStandardController(
    (new W3CAnalyzerFactory())
    ->build()
);
或者,他们希望使用自己的DI设置。正如您所说,它们如何注入并不重要,只是它们可以使用
W3CAnalyzerFactory
类,然后一切都准备就绪

提示:对于我的库和/或应用程序中的所有对象,我总是创建一个factory类,即使没有注入任何内容。一开始感觉很冗长,但有几个好处

  • 如果您曾经重构一个类(比如
    HttpClient
    ),使它现在确实需要注入一些东西,那么使用
    HttpClientFactory
    的所有工作都已经完成了,您不需要用
    (new HttpClientFactory)->build()
    替换所有
    新的HttpClient()
  • 在构建这些工厂时,您不必记住哪些注入实现需要工厂,哪些不需要工厂。一切都是这样,所以只要使用工厂。(也就是说,我是使用
    新的HttpClient
    还是
    (新的HttpClientFactory)->build()
    ?不用想,只要使用工厂就可以了。)
  • 我建议您在创建实现时创建这些工厂,因为这样可以省事,而且不需要您稍后再来考虑如何将事情组合在一起

    我认为当您不想或无法使用容器来帮助您时,这种方法对于依赖项注入来说是最简单的


    旁注:我将对象分配给
    $Subject
    ,然后
    返回$Subject
    一个单独的行,而不是只执行
    返回新内容…
    ,原因是我倾向于选择setter注入,这意味着我需要在构建对象后对其执行操作。不过,您要做最适合您的库和/或应用程序的事情。选择单词“subject”作为变量名是因为在我的单元测试中调用我的对象来表示“subject Under Test”。这些对象没有经过测试,所以我只是将它们命名为
    $Subject
    ,以获得一个很好的一致性名称,帮助我轻松地看到正在构造的对象是什么。同样,我的这个习惯完全是可以选择的。

    @RyanVincent我已经提供了一些额外的解释。依赖注入是一个原则。您的类
    WebStandardController
    使用它。依赖项注入容器不需要使用DI。这只是一种使用单个调用创建对象及其依赖项的方便方法。@axiac和依赖项将自动解析?你读过我的帖子吗?DIC会自动解决依赖关系吗?我不这么认为;它需要配置。您的库是否导出了如此多的类,以至于需要一个DIC容器来构建它们?一次或几次还不够吗?如果你想让你的库的用户注入他们自己的
    HttpClient
    实现,那么库中嵌入的DIC就会妨碍你。它需要配置——这就是重点和问题所在。如何使此配置与不同的框架兼容,或者与仅使用composer的普通PHP项目兼容,这是我的问题。我不明白工厂在我的情况下会如何帮助我(我知道ofc工厂和工厂方法模式是什么)。你能举个例子吗?那太好了。