在PHP中寻找一种优雅的方式来加载依赖项/服务/配置? [英] Searching for an elegant way in PHP for loading dependencies/services/configuration?

查看:76
本文介绍了在PHP中寻找一种优雅的方式来加载依赖项/服务/配置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个MVC PHP框架,我想知道哪种最佳方法可以在我的类(无论是其他类还是纯配置)中加载所需的内容.

I'm building a MVC PHP framework and I wonder which are the best practices to load what I need in my classes, be it other classes or plain configuration.

直到今天,我一直使用单例,注册表和最近的依赖项注入容器. 尽管许多人声称DI是必经之路,但在我看来,这只是将组件之间的耦合问题转移到另一个地方.

Till today I've used singletons, registry and lately a dependency injection container. While many people claim that DI is the way to go, it seems to me like it justs moves the problem of coupling between components into another place.

子集引入全局状态,注册表引入紧密耦合,DI引入...很好,非常复杂.我仍然很困惑,找不到找到彼此联系的正确方法.

Singletons introduce global state, registry introduces tight coupling and DI introduces... well, lots of complexity. I am still confused and can't find a proper way to wire my classes each other.

与此同时,我想出了一个自定义解决方案.实际上,这不是解决方案,它只是从我的代码中抽象出了服务加载的实现.

In the meanwhile, I came up with a custom solution. Actually it's not a solution, it just abstracts the implementation of service loading from my code.

我使用_load_service和_load_config方法构建了一个抽象类,框架的所有组件都对其进行了扩展,以加载其他服务或配置.

I built an abstract class with _load_service and _load_config methods which all the components of my framework extend in order to load other services or configuration.

abstract class Base_Component {
    function _load_service($service) {
        // could be either
        return DI_container::getInstance()->$service;

        // or
        $class = '\services\\'.$service;
        return new $class;

        // or other implementation
    }
}

现在仅在一个位置(基类)中实现了加载它们的实现,因此至少我在组件中摆脱了如下代码行:

The implementation of loading them is now implemented in only one place, the base class, so at least I got rid of code lines like the following into my components:

$database = new Database(Registry::getInstance()->load('db_config'));

$database = DI_container::getInstance()->database;

现在,如果我想要一个数据库实例,

Now if want a database instance I do this

$database = $this->_load_service('database');

以及服务加载器,容器,注册表或其他任何东西的实现都可以在一个类方法中轻松更改,而不必搜索我的所有代码即可将调用更改为我以前使用的任何容器实现.

and the implementation of service loader, container, registry or whatever can be easily changed in a single class method without having to search through all my code to change calls to whatever container implementation I was using before.

但是正如我所说,我什至无法确定我将使用哪种方法来加载类和配置.

But as I said I'm not even close to sure about what method I will use for loading classes and configuration.

您对此有何看法?

推荐答案

为什么要重新发明轮子?使用 Pimple 作为DI容器,并从其文档中学习如何使用它.

Why reinvent the wheel? Use Pimple as your DI container, and learn how to use it from its documentation.

或者,使用 Silex 微框架作为创建自己的框架的基础.它扩展了Pimple功能,因此您可以使用依赖项注入.

Or, use Silex microframework as a base to create your own framework. It extends Pimple functionality, so you can use dependency injection.

要回答您的问题,这是如何在不将类与其耦合的情况下使用DI:

To answer your question, this is how you use a DI without coupling your classes to it:

interface ContainerInterface {
    public function getService($service_name);
    public function registerService($service_name,Closure $service_definition);
}

class Application {
    public function __construct(ContainerInterface $container) {
        $this->container= $container;
    }

    public function run() {
        // very simple to use!
        $this->container->getService('db')->someDatabaseQuery();
    }
}

$c = new My_DI_Container;

// Service definitions could be in a separate file
$c->registerService('db',function() { return new Database('some config'); });

// Then you inject your DI container into the objects that need it
$app = new Application($c);
$app->run(); // or whatever

这样,DI容器将解耦,将来您可以使用其他实现.唯一的要求是它必须实现ContainerInterface.

This way, the DI container is decoupled and in the future you could use a different implementation. The only requirement is that it implements the ContainerInterface.

请注意,容器对象是被推动而不是被拉动的.避免使用单例.要获取/设置单实例对象,请使用容器(这是它的责任).而要获取容器实例,只需将其通过构造函数推送即可.

Note that the container object is being pushed, and not pulled. Avoid using singleton. To get/set single-instance objects, use the container (that's its responsibility). And to get the container instance, just push it through constructors.

这篇关于在PHP中寻找一种优雅的方式来加载依赖项/服务/配置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆