Symfony 7.1.7 + API Platform 4.0.8 装饰不存在的"api_platform.listener.request.deserialize"服务报错解决方法
我在用Insomnia测试基于Symfony 7.1.7和API Platform 4.0.8开发的API时,发送请求后遇到了这个错误:
The service "App\EventListener\DeserializeListener" has a dependency on a non-existent service "api_platform.listener.request.deserialize".
我的DeserializeListener.php代码如下:
<?php namespace App\EventListener; use ApiPlatform\Symfony\EventListener\DeserializeListener as DecoratedListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; class DeserializeListener { public function __construct(private DecoratedListener $decorated) { } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); if($request->isMethodCacheable() || $request->isMethod(Request::METHOD_DELETE)) { return; } dd($request->getContent()); } }
services.yaml中的配置:
services: # default configuration for services in *this* file _defaults: autowire: true # Automatically injects dependencies in your services. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name App\: resource: '../src/' exclude: - '../src/DependencyInjection/' - '../src/Entity/' - '../src/Kernel.php' # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones App\OpenApi\OpenApiFactory: decorates: 'api_platform.openapi.factory' arguments: ['@App\OpenApi\OpenApiFactory.inner'] autoconfigure: false App\StateProvider\DependenciesStateProvider: arguments: $rootPath: '%kernel.project_dir%' App\StateProcessor\DependenciesStateProcessor: arguments: $rootPath: '%kernel.project_dir%' App\EventListener\DeserializeListener: tags: - { name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest', priority: 2 } autoconfigure: false decorates: 'api_platform.listener.request.deserialize' arguments: $decorated: '@App\EventListener\DeserializeListener.inner'
我发现用IDE自动补全api_platform.listener.request.deserialize时图标是灰色的,参考的教程版本比较老,试过换decorates的值但不知道选什么,请问该怎么解决这个问题?
问题原因
你遇到的问题是因为API Platform 4.0+版本中,反序列化监听器的服务ID已经发生了变化——旧教程里的api_platform.listener.request.deserialize在4.x版本中不再被使用,现在该服务的ID是它的完全限定类名ApiPlatform\Symfony\EventListener\DeserializeListener。
另外你的装饰器代码还有一个小问题:没有调用被装饰服务的原方法,这会导致原本的反序列化逻辑完全不执行,API无法正常处理请求内容。
解决方案
1. 修正services.yaml中的装饰配置
把decorates的值替换为API Platform 4.x中反序列化监听器的正确服务ID(即类名),同时可以用@.inner简化被装饰服务的引用:
App\EventListener\DeserializeListener: tags: - { name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest', priority: 11 # 如果你想在反序列化前执行逻辑,优先级要高于原监听器的10;如果想在之后执行,设为9即可 } autoconfigure: false decorates: 'ApiPlatform\Symfony\EventListener\DeserializeListener' arguments: $decorated: '@.inner'
2. 完善自定义监听器的逻辑
在onKernelRequest方法末尾,调用被装饰服务的原方法,确保原有的反序列化逻辑能正常执行:
<?php namespace App\EventListener; use ApiPlatform\Symfony\EventListener\DeserializeListener as DecoratedListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; class DeserializeListener { public function __construct(private DecoratedListener $decorated) { } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); if($request->isMethodCacheable() || $request->isMethod(Request::METHOD_DELETE)) { return; } dd($request->getContent()); // 调用原监听器的方法,保证反序列化逻辑正常运行 $this->decorated->onKernelRequest($event); } }
3. 验证配置
清理Symfony缓存(php bin/console cache:clear),然后重新用Insomnia测试请求,错误应该会消失,同时你能看到请求内容的调试输出,之后原反序列化逻辑也会正常执行。
备注:内容来源于stack exchange,提问作者user28171371

