gpt4 book ai didi

php - Symfony - 更改 Controller 的实例化和执行方式

转载 作者:行者123 更新时间:2023-12-03 00:18:00 25 4
gpt4 key购买 nike

Note: as of version 2.8, Symfony provided autowire: true for service configuration, and as of version 3.3, Symfony provided alias (instead of autowire_types) to alias a concrete object to an interface for automatic dependency injection into 'controllers as services'. There's also a bundle to allow autowiring for controller 'action' methods, although I've moved away from this and have focussed more on a variation of the ADR pattern (which is, basically, a single 'action' class with an interface method and not shoving a load of actions methods within a single class which eventually makes for an architectural nightmare). This is, effectively, what I've been looking for all these years and now no longer need to 'hook-in' a decent recursive dependency injector (auryn) as the framework now handles what it should have four years previous. I'll leave this answer here in case anyone wants to trace the steps that I did to see how the kernel works and some of the options available at this level.

<小时/>

Note: Although this question primarily targets Symfony 3, it should also be relevant to users of Symfony 2 as the kernel logic doesn't seem to have changed much.

我想更改 Symfony 中 Controller 的实例化方式。它们实例化的逻辑当前位于 HttpKernel::handle更具体地说,HttpKernel::handleRaw 。我想用我自己执行该特定行的注入(inject)器替换 call_user_func_array($controller, $arguments)

到目前为止我尝试过的选项:

  • 使用我自己的方法扩展HttpKernel::handle,然后由 symfony 调用
http_kernel:
class: AppBundle\HttpKernel
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']

这样做的缺点是,因为 handleRaw 是私有(private)的,所以我无法在没有黑客反射的情况下扩展它,因此我必须复制并粘贴大量代码。

  • 创建并注册新的 Controller 解析器
controller_resolver:
class: AppBundle\ControllerResolver
arguments: []

这是我的一个根本性误解,所以我想我应该在这里记录下来。解析器的工作是解析where以找到可调用的 Controller 。它实际上还没有被调用。我对 Symfony 如何从 routes.yml 获取路由并找出将 Controller 作为可调用对象调用的类和方法感到非常满意。

  • kernel.request 上添加事件监听器
kernel.request:
class: MyCustomRequestListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 33 /** Important, we'll get to why in a minute **/ }

看看 Http Kernel Component Documentation ,我们可以看到它有以下典型目的:

To add more information to the Request, initialise parts of the system, or return a Response if possible (e.g. a security layer that denies access).

我认为通过创建一个新的监听器,使用自定义注入(inject)器创建 Controller ,然后在该监听器中返回响应,将绕过实例化 Controller 的其余代码。 这就是我想要的!但这有一个重大缺陷:

Symfony Profiler 没有出现或任何类似的东西,这只是我的回应,仅此而已。死了。我发现我可以将优先级从 31 切换到 33,并让它在我的代码和 Symfonys 之间切换,我相信这是因为路由器监听器 priority 。我觉得我走错了路。

不,这允许我更改将由 call_user_func_array() 调用的可调用,而不是 Controller 实际实例化的方式,这是我的目标。

我已经记录了我的想法,但我已经退出了。我怎样才能实现以下目标?

  • 更改 Controller 的实例化和执行方式,特别是 call_user_func_array() ,它是一个该死的私有(private)方法(感谢 Symfony)
  • 如果我的 Controller 不起作用,则返回到默认 Controller 实例化
  • 允许其他一切按预期工作,例如分析器加载
  • 能够将其与其他用户的扩展程序捆绑在一起
<小时/>

为什么我要这样做?

Controller 可以针对不同的情况有许多不同的方法,并且每个方法应该能够针对其单独需要的内容进行键入提示,而不是让构造函数获取所有内容,其中一些内容甚至可能不会被使用,具体取决于正在执行的 Controller 方法。 Controller 并不真正遵守单一职责原则,并且它们是“对象边缘情况”。但他们就是他们。

我想用我自己的递归 Autowiring 注入(inject)器来替换 Controller 的创建方式,以及它们的执行方式,再次通过我的注入(inject)器进行递归内省(introspection),因为默认的 Symfony 包似乎没有此功能。即使使用 Symfony 2.8+ 中最新的“autowire”服务选项。

最佳答案

Controller 解析器实际上做了两件事。首先是获取 Controller 。第二个是获取给定操作的参数列表。

$arguments = $this->resolver->getArguments($request, $controller);
$response = call_user_func_array($controller, $arguments);

您可以重写 getArguments 方法来实现特殊的“操作方法注入(inject)”功能。您只需确定操作方法需要哪些参数并返回它们的数组。

基于另一个问题,我还认为您可能误解了 Autowiring 功能。 Autowire 实际上只适用于构造函数注入(inject)。它对操作方法注入(inject)没有帮助。

如果 getArguments 不能满足您的要求,那么重写句柄方法实际上是您唯一的选择。是的,有相当多的代码需要从handleRaw复制/粘贴,但那是因为那里有很多事情要做。即使handleRaw 受到保护,您仍然需要复制/粘贴代码才能找到您想要替换的一行。

关于php - Symfony - 更改 Controller 的实例化和执行方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34875323/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com