我发现了一个 Drupal 站点的错误,我们正在升级到 Drupal 10:
类型错误:Drupal\my_module\Controller\ApiController::catchAll(): 参数 #1 ($request) 必须是类型 Symfony\Component\HttpFoundation\Request, Drupal\my_module\Entity\Channel 中给出 Drupal\my_module\Controller\ApiController->catchAll() (第 50 行 模块/自定义/my_module/src/Controller/ApiController.php)。
我们...似乎正在使用自定义服务通过编译器通道将当前通道注入控制器,在我们尝试升级到 D10 之前,该服务运行良好。现在看起来...传递给控制器的每个参数都是一个 Channel 实例?
服务定义:
my_module.argument_resolver.channel_resolver:
class: Drupal\my_module\Resolver\ChannelResolver
arguments:
- '@entity_type.manager'
autowire: true
tags:
- { name: controller.argument_value_resolver, priority: 50 }
服务提供商:
class MyModuleServiceProvider extends ServiceProviderBase
{
/**
* {@inheritdoc}
*/
public function register(ContainerBuilder $container)
{
$container->addCompilerPass(new ControllerArgumentValueResolverPass('http_kernel.controller.argument_resolver'));
}
}
编译通过:
class ControllerArgumentValueResolverPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
private $argumentResolverService;
private $argumentValueResolverTag;
public function __construct($argumentResolverService = 'argument_resolver', $argumentValueResolverTag = 'controller.argument_value_resolver')
{
$this->argumentResolverService = $argumentResolverService;
$this->argumentValueResolverTag = $argumentValueResolverTag;
}
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition($this->argumentResolverService)) {
return;
}
$container
->getDefinition($this->argumentResolverService)
->replaceArgument(1,
array_merge(
$this->findAndSortTaggedServices($this->argumentValueResolverTag, $container),
$container->getDefinition($this->argumentResolverService)->getArgument(1)
));
}
}
如果还不清楚的话,我...几乎不知道这段代码在做什么。但是我们有一个错误,控制器没有获得它期望的参数,并且此代码似乎正在更改传递给控制器的参数。对于问题的模糊性表示歉意,但是有人对如何调试这个有任何建议吗?或者为什么它可能与 D10 有关?
您似乎正在使用自定义服务通过编译器传递将 'Channel' 实体注入控制器参数中。过渡到 Drupal 10 似乎导致控制器方法的预期参数类型与传递的实际参数之间发生冲突。这可能是由于 Symfony 或 Drupal 核心的内部更改可能会影响编译器传递的行为。
调试步骤
检查 Drupal 10 和 Symfony 文档: 该问题可能与 Drupal 10 或 Symfony 中的更改有关,尤其是它们处理服务参数或控制器参数解析器的方式。 查看 Drupal 10 和 Symfony 的迁移文档,看看是否有任何重大更改。
调试编译器通道:在 ControllerArgumentValueResolverPass 类中,您可以添加调试语句来打印传递给控制器的参数。这应该可以帮助您了解编译过程中实际发生的情况。
public function process(ContainerBuilder $container)
{
// Add debug statements here
print_r($container->getDefinition($this->argumentResolverService)->getArgument(1));
// Existing code...
}
控制器中的类型检查:在调用控制器逻辑之前,添加类型检查以查看实际传递的参数类型。
public function catchAll($request) {
if (!($request instanceof Request)) {
throw new \InvalidArgumentException('Invalid argument type');
}
// Rest of the code
}
检查解析器:检查您的 ChannelResolver 类以确保它解析为正确的类型。如果它将所有问题都解析到 Channel 实体,那么它可能就是罪魁祸首。
调整优先级:您已为自定义解析器设置优先级 50。尝试更改此优先级以确保它不会覆盖其他重要的解析器。
tags:
- { name: controller.argument_value_resolver, priority: 10 } # Changed priority
解决问题
根据调试过程中发现的内容,您可能需要:
修改您的 ChannelResolver,使其在解决参数方面更具选择性,尤其是现在您使用的是 Drupal 10。 更新控制器方法签名以接受不同类型的参数,并使用运行时检查来相应地处理它们。 更改应用自定义参数解析器的优先级或条件。
了解 Symfony 的服务容器、参数解析器和编译器传递如何工作对于调试此问题至关重要。鉴于您要升级到 Drupal 10,这些知识不仅可以帮助您解决此问题,还可以帮助您解决迁移过程中可能出现的其他问题。
希望这有帮助。