是什么导致 Symfony 调用服务?
What causes Symfony to call a service?
我有一个问题,与其问如何解决它,不如更好地了解正在发生的事情,以便我自己解决它。
使用 api-platform 2.6.6,我成功地向 SwaggerUI 添加了一个端点以检索 JWT 令牌。我后来升级到 api-platform 2.7.x-dev 并且端点不再显示。虽然我的最终目标是恢复端点,但我的直接目标是更好地了解 Symfony 是如何配置为调用服务的。
根据 2.6.6 api 平台文档 to add the endpoint 添加了装饰器并将其注册为服务。
api/src/OpenApi/JwtDecorator.php
<?php
declare(strict_types=1);
namespace App\OpenApi;
use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\Core\OpenApi\OpenApi;
use ApiPlatform\Core\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
// script goes here.
}
}
api/config/services.yaml
services:
# ...
App\OpenApi\JwtDecorator:
decorates: 'api_platform.openapi.factory'
arguments: ['@.inner']
为确保此单一服务单独负责添加端点,我有意未对 api/config/packages/security.yaml
、api/config/routes.yaml
和 api/config/packages/api_platform.yaml
进行任何更改,以确保它们不是导致端点显示在原始 2.6.6 版本上,但事实并非如此。我还查看了使用 composer 安装 jwt-auth
时所做的更改,似乎没有任何相关内容。我还发现我可以将 JwtDecorator 重命名为 SomeOtherName 并排除了 class 名称具有特殊含义的可能性。
接下来,我在class之外的App\OpenApi\JwtDecorator
文件中放置了一个debug_print_backtrace()
,发现无论是使用2.6.6还是2.7.x- dev,命令被执行并且回溯是相同的。我的假设是,根据任何请求,symfony 将首先对位于 src
中具有 php
扩展名的每个文件执行 include()
(除非明确指示不要在某些配置文件中执行),检查是否缓存是新鲜的(如果没有创建缓存文件),并使用结果填充服务容器。请确认是否正确。
api/src/OpenApi/JwtDecorator.php 文件中的回溯(不在构造函数中)
#0 include() called at [/srv/api/vendor/symfony/error-handler/DebugClassLoader.php:349] # line 349 for 2.6.6 and 346 for 2.7.x-dev.
#1 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass()
#2 ReflectionClass->__construct() called at [/srv/api/vendor/symfony/config/Resource/ReflectionClassResource.php:107]
#3 Symfony\Component\Config\Resource\ReflectionClassResource->computeHash() called at [/srv/api/vendor/symfony/config/Resource/ReflectionClassResource.php:54]
#4 Symfony\Component\Config\Resource\ReflectionClassResource->isFresh() called at [/srv/api/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php:34]
#5 Symfony\Component\Config\Resource\SelfCheckingResourceChecker->isFresh() called at [/srv/api/vendor/symfony/config/ResourceCheckerConfigCache.php:99]
#6 Symfony\Component\Config\ResourceCheckerConfigCache->isFresh() called at [/srv/api/vendor/symfony/config/ConfigCache.php:60]
#7 Symfony\Component\Config\ConfigCache->isFresh() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:451]
#8 Symfony\Component\HttpKernel\Kernel->initializeContainer() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:786]
#9 Symfony\Component\HttpKernel\Kernel->preBoot() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:187]
#10 Symfony\Component\HttpKernel\Kernel->handle() called at [/srv/api/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:37]
#11 Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() called at [/srv/api/vendor/autoload_runtime.php:35]
#12 require_once(/srv/api/vendor/autoload_runtime.php) called at [/srv/api/public/index.php:5]
接下来,我做了同样的事情,但这次是在 JwtDecorator 的构造函数中,它只执行了 2.6.6 而不是 2.7.x-dev。现在我知道没有显示端点,因为没有调用装饰器。
然后我开始查看 ContainerIx5JWFD 中的 classes,我发现 class 的名称始终是“get”+ servicesClassName +“service”。现在我明白了为什么我能够将服务名称从 JwtDecorator 更改为 SomeOtherName 并且它仍然有效。我还发现 ContainerIx5JWFD\getJwtDecoratorService
class 只存在于 2.6.6 而不是 2.7.x-dev.
2.6.6 回溯 JwtDecorator::__construct()
#0 App\OpenApi\JwtDecorator->__construct() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getJwtDecoratorService.php:25]
#1 ContainerIx5JWFD\getJwtDecoratorService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#2 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getApiPlatform_SwaggerUi_ActionService.php:23]
#3 ContainerIx5JWFD\getApiPlatform_SwaggerUi_ActionService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#4 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getApiPlatform_Swagger_Action_UiService.php:22]
#5 ContainerIx5JWFD\getApiPlatform_Swagger_Action_UiService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#6 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/vendor/symfony/dependency-injection/Container.php:237]
#7 Symfony\Component\DependencyInjection\Container->make() called at [/srv/api/vendor/symfony/dependency-injection/Container.php:219]
#8 Symfony\Component\DependencyInjection\Container->get() called at [/srv/api/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:53]
#9 Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->instantiateController() called at [/srv/api/vendor/symfony/framework-bundle/Controller/ControllerResolver.php:29]
#10 Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver->instantiateController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ControllerResolver.php:108]
#11 Symfony\Component\HttpKernel\Controller\ControllerResolver->createController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:42]
#12 Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->createController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ControllerResolver.php:86]
#13 Symfony\Component\HttpKernel\Controller\ControllerResolver->getController() called at [/srv/api/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php:38]
#14 Symfony\Component\HttpKernel\Controller\TraceableControllerResolver->getController() called at [/srv/api/vendor/symfony/http-kernel/HttpKernel.php:139]
#15 Symfony\Component\HttpKernel\HttpKernel->handleRaw() called at [/srv/api/vendor/symfony/http-kernel/HttpKernel.php:78]
#16 Symfony\Component\HttpKernel\HttpKernel->handle() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:199]
#17 Symfony\Component\HttpKernel\Kernel->handle() called at [/srv/api/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:37]
#18 Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() called at [/srv/api/vendor/autoload_runtime.php:35]
#19 require_once(/srv/api/vendor/autoload_runtime.php) called at [/srv/api/public/index.php:5]
因此,要解决此问题,我不应该遵循此代码路径,而应该遵循创建这些缓存文件的代码。我被困住了并乞求帮助。是什么触发 Symfony 创建这些 classes 以便调用服务?我如何确定 2.6.6 和 2.7.x-dev 之间的区别,以便它仅在 2.6.6 上调用?
最重要的信息:等待该库的正式发布,因为它将包含升级列表。重命名服务(就像这里发生的那样)可能会在此处列出。
进入正题:通过在源代码中搜索 api_platform.openapi.factory
,我发现该服务已在 pull request 中重命名。新的服务名称是 api_platform.openapi.factory.next
我有一个问题,与其问如何解决它,不如更好地了解正在发生的事情,以便我自己解决它。
使用 api-platform 2.6.6,我成功地向 SwaggerUI 添加了一个端点以检索 JWT 令牌。我后来升级到 api-platform 2.7.x-dev 并且端点不再显示。虽然我的最终目标是恢复端点,但我的直接目标是更好地了解 Symfony 是如何配置为调用服务的。
根据 2.6.6 api 平台文档 to add the endpoint 添加了装饰器并将其注册为服务。
api/src/OpenApi/JwtDecorator.php
<?php
declare(strict_types=1);
namespace App\OpenApi;
use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\Core\OpenApi\OpenApi;
use ApiPlatform\Core\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
// script goes here.
}
}
api/config/services.yaml
services:
# ...
App\OpenApi\JwtDecorator:
decorates: 'api_platform.openapi.factory'
arguments: ['@.inner']
为确保此单一服务单独负责添加端点,我有意未对 api/config/packages/security.yaml
、api/config/routes.yaml
和 api/config/packages/api_platform.yaml
进行任何更改,以确保它们不是导致端点显示在原始 2.6.6 版本上,但事实并非如此。我还查看了使用 composer 安装 jwt-auth
时所做的更改,似乎没有任何相关内容。我还发现我可以将 JwtDecorator 重命名为 SomeOtherName 并排除了 class 名称具有特殊含义的可能性。
接下来,我在class之外的App\OpenApi\JwtDecorator
文件中放置了一个debug_print_backtrace()
,发现无论是使用2.6.6还是2.7.x- dev,命令被执行并且回溯是相同的。我的假设是,根据任何请求,symfony 将首先对位于 src
中具有 php
扩展名的每个文件执行 include()
(除非明确指示不要在某些配置文件中执行),检查是否缓存是新鲜的(如果没有创建缓存文件),并使用结果填充服务容器。请确认是否正确。
api/src/OpenApi/JwtDecorator.php 文件中的回溯(不在构造函数中)
#0 include() called at [/srv/api/vendor/symfony/error-handler/DebugClassLoader.php:349] # line 349 for 2.6.6 and 346 for 2.7.x-dev.
#1 Symfony\Component\ErrorHandler\DebugClassLoader->loadClass()
#2 ReflectionClass->__construct() called at [/srv/api/vendor/symfony/config/Resource/ReflectionClassResource.php:107]
#3 Symfony\Component\Config\Resource\ReflectionClassResource->computeHash() called at [/srv/api/vendor/symfony/config/Resource/ReflectionClassResource.php:54]
#4 Symfony\Component\Config\Resource\ReflectionClassResource->isFresh() called at [/srv/api/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php:34]
#5 Symfony\Component\Config\Resource\SelfCheckingResourceChecker->isFresh() called at [/srv/api/vendor/symfony/config/ResourceCheckerConfigCache.php:99]
#6 Symfony\Component\Config\ResourceCheckerConfigCache->isFresh() called at [/srv/api/vendor/symfony/config/ConfigCache.php:60]
#7 Symfony\Component\Config\ConfigCache->isFresh() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:451]
#8 Symfony\Component\HttpKernel\Kernel->initializeContainer() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:786]
#9 Symfony\Component\HttpKernel\Kernel->preBoot() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:187]
#10 Symfony\Component\HttpKernel\Kernel->handle() called at [/srv/api/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:37]
#11 Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() called at [/srv/api/vendor/autoload_runtime.php:35]
#12 require_once(/srv/api/vendor/autoload_runtime.php) called at [/srv/api/public/index.php:5]
接下来,我做了同样的事情,但这次是在 JwtDecorator 的构造函数中,它只执行了 2.6.6 而不是 2.7.x-dev。现在我知道没有显示端点,因为没有调用装饰器。
然后我开始查看 ContainerIx5JWFD 中的 classes,我发现 class 的名称始终是“get”+ servicesClassName +“service”。现在我明白了为什么我能够将服务名称从 JwtDecorator 更改为 SomeOtherName 并且它仍然有效。我还发现 ContainerIx5JWFD\getJwtDecoratorService
class 只存在于 2.6.6 而不是 2.7.x-dev.
2.6.6 回溯 JwtDecorator::__construct()
#0 App\OpenApi\JwtDecorator->__construct() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getJwtDecoratorService.php:25]
#1 ContainerIx5JWFD\getJwtDecoratorService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#2 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getApiPlatform_SwaggerUi_ActionService.php:23]
#3 ContainerIx5JWFD\getApiPlatform_SwaggerUi_ActionService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#4 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/getApiPlatform_Swagger_Action_UiService.php:22]
#5 ContainerIx5JWFD\getApiPlatform_Swagger_Action_UiService::do() called at [/srv/api/var/cache/dev/ContainerIx5JWFD/App_KernelDevDebugContainer.php:644]
#6 ContainerIx5JWFD\App_KernelDevDebugContainer->load() called at [/srv/api/vendor/symfony/dependency-injection/Container.php:237]
#7 Symfony\Component\DependencyInjection\Container->make() called at [/srv/api/vendor/symfony/dependency-injection/Container.php:219]
#8 Symfony\Component\DependencyInjection\Container->get() called at [/srv/api/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:53]
#9 Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->instantiateController() called at [/srv/api/vendor/symfony/framework-bundle/Controller/ControllerResolver.php:29]
#10 Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver->instantiateController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ControllerResolver.php:108]
#11 Symfony\Component\HttpKernel\Controller\ControllerResolver->createController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php:42]
#12 Symfony\Component\HttpKernel\Controller\ContainerControllerResolver->createController() called at [/srv/api/vendor/symfony/http-kernel/Controller/ControllerResolver.php:86]
#13 Symfony\Component\HttpKernel\Controller\ControllerResolver->getController() called at [/srv/api/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php:38]
#14 Symfony\Component\HttpKernel\Controller\TraceableControllerResolver->getController() called at [/srv/api/vendor/symfony/http-kernel/HttpKernel.php:139]
#15 Symfony\Component\HttpKernel\HttpKernel->handleRaw() called at [/srv/api/vendor/symfony/http-kernel/HttpKernel.php:78]
#16 Symfony\Component\HttpKernel\HttpKernel->handle() called at [/srv/api/vendor/symfony/http-kernel/Kernel.php:199]
#17 Symfony\Component\HttpKernel\Kernel->handle() called at [/srv/api/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:37]
#18 Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run() called at [/srv/api/vendor/autoload_runtime.php:35]
#19 require_once(/srv/api/vendor/autoload_runtime.php) called at [/srv/api/public/index.php:5]
因此,要解决此问题,我不应该遵循此代码路径,而应该遵循创建这些缓存文件的代码。我被困住了并乞求帮助。是什么触发 Symfony 创建这些 classes 以便调用服务?我如何确定 2.6.6 和 2.7.x-dev 之间的区别,以便它仅在 2.6.6 上调用?
最重要的信息:等待该库的正式发布,因为它将包含升级列表。重命名服务(就像这里发生的那样)可能会在此处列出。
进入正题:通过在源代码中搜索 api_platform.openapi.factory
,我发现该服务已在 pull request 中重命名。新的服务名称是 api_platform.openapi.factory.next