依赖注入组件
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 4.1,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
依赖注入组件
在前一章中,我们清空了单纯形\框架
类,通过扩展HttpKernel
从同名组件初始化。看到这个空类,你可能会想把一些代码从前端控制器移到它上面:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/ / example.com/src/Simplex/Framework.php名称空间单纯形;使用ob娱乐下载\组件\EventDispatcher\EventDispatcher;使用ob娱乐下载\组件\HttpFoundation;使用ob娱乐下载\组件\HttpFoundation\RequestStack;使用ob娱乐下载\组件\HttpKernel;使用ob娱乐下载\组件\路由;类框架扩展HttpKernel\HttpKernel{公共函数__construct($路线){$上下文=新路由\ RequestContext ();$匹配器=新路由\匹配器\ UrlMatcher ($路线,$上下文);$requestStack=新RequestStack ();$controllerResolver=新HttpKernel \控制器\ ControllerResolver ();$argumentResolver=新HttpKernel \控制器\ ArgumentResolver ();$调度程序=新EventDispatcher ();$调度程序->addSubscriber (新HttpKernel \ EventListener \ RouterListener ($匹配器,$requestStack));$调度程序->addSubscriber (新HttpKernel \ EventListener \ ResponseListener (“utf - 8”));父::__construct ($调度程序,$controllerResolver,$requestStack,$argumentResolver);}}
前端控制器代码将变得更加简洁:
1 2 3 4 5 6 7 8 9 10 11
/ / example.com/web/front.phprequire_once__DIR__.“/ . . /供应商/ autoload.php”;使用ob娱乐下载\组件\HttpFoundation\请求;$请求=请求::createFromGlobals ();$路线=包括__DIR__.“/ . . / src / app.php”;$框架=新单纯形\框架($路线);$框架->处理($请求)->send ();
拥有简洁的前端控制器可以让您为单个应用程序拥有多个前端控制器。为什么它有用?例如,允许对开发环境和生产环境进行不同的配置。在开发环境中,您可能希望打开错误报告,并在浏览器中显示错误,以简化调试:
1 2
报错(“display_errors”,1);error_reporting (-1);
...但是您肯定不希望在生产环境中使用相同的配置。拥有两个不同的前控制器可以让你有机会为每个控制器设置略微不同的配置。
因此,将代码从前端控制器移动到框架类使我们的框架更具可配置性,但与此同时,它引入了很多问题:
- 我们不能再注册自定义监听器了,因为分派器在Framework类之外是不可用的(一个简单的解决方法是添加一个
框架::getEventDispatcher ()
方法); - 我们已经失去了以前的灵活性;方法的实现不能更改
UrlMatcher
或者ControllerResolver
了; - 与前一点相关,我们不能再轻松地测试我们的框架,因为它不可能模拟内部对象;
- 不能更改传递到的字符集
ResponseListener
任何(一种变通方法是将其作为构造函数参数传递)。
前面的代码没有出现同样的问题,因为我们使用了依赖注入;对象的所有依赖关系都被注入到它们的构造函数中(例如,事件分派器被注入到框架中,这样我们就可以完全控制它的创建和配置)。
这是否意味着我们必须在灵活性、自定义、易于测试和不复制和粘贴相同的代码到每个应用程序前端控制器之间做出选择?正如你所期望的,有一个解决方案。我们可以通过使用Symfony依赖注入容器来解决所有这些问题:ob娱乐下载
1
$Composer需要symfonyob娱乐下载/依赖注入
创建一个新文件来存放依赖注入容器配置:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/ / example.com/src/container.php使用ob娱乐下载\组件\DependencyInjection;使用ob娱乐下载\组件\DependencyInjection\参考;使用ob娱乐下载\组件\HttpFoundation;使用ob娱乐下载\组件\HttpKernel;使用ob娱乐下载\组件\路由;使用ob娱乐下载\组件\EventDispatcher;使用单纯形\框架;$containerBuilder=新DependencyInjection \ ContainerBuilder ();$containerBuilder->注册(“背景”、路由\ RequestContext::类);$containerBuilder->注册(“匹配器”、路由\匹配器\ UrlMatcher::类)->setArguments ([$路线,新引用(“背景”)));$containerBuilder->注册(“request_stack”, HttpFoundation \ RequestStack::类);$containerBuilder->注册(“controller_resolver”控制器,HttpKernel \ \ ControllerResolver::类);$containerBuilder->注册(“argument_resolver”控制器,HttpKernel \ \ ArgumentResolver::类);$containerBuilder->注册(“listener.router”, HttpKernel \ EventListener \ RouterListener::类)->setArguments ([新引用(“匹配器”),新引用(“request_stack”)));$containerBuilder->注册(“listener.response”, HttpKernel \ EventListener \ ResponseListener::类)->setArguments ([“utf - 8”]);$containerBuilder->注册(“listener.exception”, HttpKernel \ EventListener \ ExceptionListener::类)->setArguments ([“日历\控制器\ ErrorController:异常”]);$containerBuilder->注册(“调度”, EventDispatcher \ EventDispatcher::类)->addMethodCall (“addSubscriber”, (新引用(“listener.router”)))->addMethodCall (“addSubscriber”, (新引用(“listener.response”)))->addMethodCall (“addSubscriber”, (新引用(“listener.exception”)));$containerBuilder->注册(“框架”,框架::类)->setArguments ([新引用(“调度”),新引用(“controller_resolver”),新引用(“request_stack”),新引用(“argument_resolver”),]);返回$containerBuilder;
该文件的目标是配置对象及其依赖项。在这个配置步骤中没有实例化任何东西。这纯粹是对需要操作的对象以及如何创建它们的静态描述。当您从容器中访问对象时,或者当容器需要它们来创建其他对象时,对象将按需创建。
例如,要创建路由器侦听器,我们告诉Symfony它的类名是ob娱乐下载ob娱乐下载
并且它的构造函数接受一个matcher对象(新的参考(“匹配器”)
).如您所见,每个对象都由名称引用,名称是唯一标识每个对象的字符串。该名称允许我们获取一个对象,并在其他对象定义中引用它。
请注意
默认情况下,每次从容器中获取对象时,它都会返回完全相同的实例。这是因为容器管理着“全局”对象。
前端控制器现在只是将所有东西连接在一起:
12 3 4 5 6 7 8 9 10 11 12 13
/ / example.com/web/front.phprequire_once__DIR__.“/ . . /供应商/ autoload.php”;使用ob娱乐下载\组件\HttpFoundation\请求;$路线=包括__DIR__.“/ . . / src / app.php”;$容器=包括__DIR__.“/ . . / src / container.php”;$请求=请求::createFromGlobals ();$响应=$容器->get (“框架”)->处理($请求);$响应->send ();
因为现在所有的对象都是在依赖注入容器中创建的,所以框架代码应该是之前的简单版本:
1 2 3 4 5 6 7 8
/ / example.com/src/Simplex/Framework.php名称空间单纯形;使用ob娱乐下载\组件\HttpKernel\HttpKernel;类框架扩展HttpKernel{}
请注意
如果您想要一个更轻的容器替代品,请考虑一下丘疹,一个简单的依赖注入容器,大约60行PHP代码。
现在,下面是如何在前端控制器中注册一个自定义监听器:
1 2 3 4 5 6 7
/ /……使用单纯形\StringResponseListener;$容器->注册(“listener.string_response”, StringResponseListener::类);$容器->getDefinition (“调度”)->addMethodCall (“addSubscriber”, (新引用(“listener.string_response”)));
除了描述对象外,依赖注入容器还可以通过参数进行配置。让我们创建一个定义是否处于调试模式的函数:
1 2 3
$容器->setParameter (“调试”,真正的);回声$容器->getParameter (“调试”);
在定义对象定义时可以使用这些参数。让我们设置字符集为可配置的:
1 2 3 4
/ /……$容器->注册(“listener.response”, HttpKernel \ EventListener \ ResponseListener::类)->setArguments ([“%字符集%”]);
在此更改之后,您必须在使用响应侦听器对象之前设置字符集:
1
$容器->setParameter (“字符集”,“utf - 8”);
而不是依赖于约定的路线是由定义美元的路线
变量,让我们再次使用一个参数:
1 2 3 4
/ /……$容器->注册(“匹配器”、路由\匹配器\ UrlMatcher::类)->setArguments ([“%路线%”,新引用(“背景”)));
以及前端控制器的相关变化:
1
$容器->setParameter (“路线”,包括__DIR__.“/ . . / src / app.php”);
显然,我们仅仅触及了容器的表面:从作为参数的类名,到覆盖现有对象定义,从共享服务支持,到将容器转储为普通PHP类,等等。Symfob娱乐下载ony依赖注入容器非常强大,能够管理任何类型的PHP类。
如果您不想在框架中使用依赖注入容器,请不要对我大喊大叫。如果你不喜欢它,就不要用它。这是你的框架,不是我的。
这是本书关于在Symfony组件之上创建框架的最后一章。ob娱乐下载我知道许多主题都没有详细介绍,但希望本文为您提供了足够的信息,使您能够自己开始学习并更好地理解Symfony框架的内部工作方式。ob娱乐下载
玩得开心!