Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.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_Oop_Dependency Injection_Module - Fatal编程技术网

Php 依赖解析设计模式

Php 依赖解析设计模式,php,oop,dependency-injection,module,Php,Oop,Dependency Injection,Module,我正在寻找类似这样的php实现或设计模式(只是一个非常基本的框架示例): 我想松散耦合我在应用程序中使用的每个模块,因此我打算设计接口,可能是带有验证的抽象类,以便为每个模块类型创建定义良好的接口。我还没有找到解决这个问题的方法,ppl通常用IoC容器来注入东西,这并没有告诉我们两个模块之间的公共接口 您知道解决这个问题的设计模式吗,或者知道解决这个问题的标准php实现/框架吗 注意:IoC容器不是一个解决方案,我想用定义良好的接口注入依赖项,而不是从DI容器或服务定位器中提取依赖项。。。我不想

我正在寻找类似这样的php实现或设计模式(只是一个非常基本的框架示例):

我想松散耦合我在应用程序中使用的每个模块,因此我打算设计接口,可能是带有验证的抽象类,以便为每个模块类型创建定义良好的接口。我还没有找到解决这个问题的方法,ppl通常用IoC容器来注入东西,这并没有告诉我们两个模块之间的公共接口

您知道解决这个问题的设计模式吗,或者知道解决这个问题的标准php实现/框架吗

注意:IoC容器不是一个解决方案,我想用定义良好的接口注入依赖项,而不是从DI容器或服务定位器中提取依赖项。。。我不想让我的模块知道他们是如何获得依赖关系的

编辑:

我更新了我的问题,因为我不认为我的代码对每个人都是显而易见的。A创建了一个类图以便于理解:

好的,这个图表包含了一个单一环境的描述。我们通常使用不同的环境,例如:测试、开发、生产等。。。每个环境都包含不同的模块,例如,通过测试和开发,我们通常会关闭电子邮件发送,因此其中一个模块在这些环境中包含一个模拟php邮件程序。。。正如您通过跨模块依赖性看到的,类依赖于契约,而不是直接依赖于彼此。这样模块的代码就松耦合了

我打算描述这种依赖关系(例如使用注释),并以某种方式自动注入它们。这是一项困难的任务,因为通过PHP,我必须只加载处理请求所需的类。例如:

class ModuleContainer {
    public function setCrossDomainDependency(Contract\Dep $crossDomainDependency){
        //...
    }

    /** @return Contract\Dep */
    public function getCrossDomainDependency(){
        //...
    }
}

所以我必须以某种方式使用惰性负载,例如我可以注入工厂,但我不喜欢这个想法,我想注入依赖项本身,而不是工厂

请注意,契约接口对其实现一无所知,因此我必须以某种方式按每个模块发布这些实现,并从其他模块中查找它们。。。大多数DI容器实现都解决了这个问题,但我不想将工厂或DI容器注入到我的模块中。我希望他们只依赖合同,而不是其他

Matthieu Napoli建议每个环境只使用一个配置不同的IoC容器,但我不认为这能解决我的问题。DI容器将实例化具有跨模块依赖关系的每个类,因此我将把每个模块的整个配置移到一个巨大的主配置文件中。即使是一个简单的项目,我也会有大约20个类(语言、用户、识别因子、用户识别因子、联系人、用户联系人、角色、用户角色、权限、角色权限、文章、评论等)和至少3个模块(表示层、业务逻辑层、数据访问层)。因此,主配置将包含来自不同模块的至少60个类的实例化。。。这将很难维护,我几乎可以肯定,这将导致不同环境的配置大量代码重复。。。是的,也许分割配置文件可以减少痛苦,但我想我不会知道这个解决方案的优点和缺点,直到我开始在一个复杂的项目上使用它。这种方法的另一个问题是,如何在不将IoC容器本身注入具有跨模块依赖性的每个类的情况下实现延迟加载?我想我需要证据或示例代码,证明这种方法在这个问题域中确实很有效

目前,我正在考虑与require.js使用AMD javascript模块类似的东西,但这也通过延迟加载注入了IoC容器。如果要加载不想在代码中使用的依赖项,就必须从模块内部使用
require(“moduleName”)
,以防万一。
require
的Ofc只是
container.get(“moduleName”)
的一种糖类语法。。。目前我不知道如何解决这个问题。我认为我的每个模块都应该有一个或多个DI容器,称它们为模块容器。这些模块容器可以处理跨模块依赖关系。通过延迟加载,模块容器将从主容器中拉下每个类的跨模块依赖项,主容器将自动注册每个模块容器和它们实例化的每个类。在这个场景中,如果我不能在不注入工厂、DI容器或服务定位器的情况下解决延迟加载,那么只有模块容器才知道主容器。。。Ofc这是最后的手段,我想我可以在不将主容器注入模块容器的情况下以某种方式进行延迟加载。或者至少我可以用sugar语法实现,例如:

class ModuleContainer {
    public function setCrossDomainDependency(Contract\Dep $crossDomainDependency){
        //...
    }

    /** @return Contract\Dep */
    public function getCrossDomainDependency(){
        //...
    }
}
我的目的是使用相同的
ModuleContainer
实例,而不管是否有
main容器
。我将检查反射api,也许我能够在运行时以某种方式重写
getCrossDomainDependency
。如果不是的话,我认为唯一的解决办法是注入工厂或主容器。。。不,但这是我的解决方案

您将如何解决此问题?

IoC容器正是解决方案

我想用定义良好的接口注入依赖项,而不是从DI容器或服务定位器中提取依赖项

然后不要将容器用作服务定位器。这正是DI容器的用途

以下是您的示例,使用:

当然,我这里的例子并不完美。我建议将配置部分与执行部分分开。我将把配置放在一个配置文件()中

重要:是的,在那个例子中
$containerBuilder = new ContainerBuilder();
$container = containerBuilder->build();

// Configure RestApi\EntryPoint to use for Contract\EntryPoint
$container->set(Contract\EntryPoint::class, \DI\link(RestApi\EntryPoint::class));

// Configure BusinessLogic\Application to use for Contract\Application
$container->set(Contract\Application::class, \DI\link(BusinessLogic\Application::class));

// Run
$entryPoint = $container->get(Contract\EntryPoint::class);
$entryPoint->handleRequest();
$container->set(Contract\EntryPoint::class, \DI\factory(function (Container $c) {
    return new RestApi\EntryPoint($c->get('some.parameter'));
}));