ZF-Rest $event->getRouteMatch() 在扩展 RestController 时为 null

ZF-Rest $event->getRouteMatch() is null when extending RestController

我在我的项目中使用 zf-rest composer 包。

这是我的资源文件中的 create 方法。

public function create($data)
{
    var_dump($e->getRouteMatch()->getParams()); 
    // all URL params are listed here with the correct values
    die();
}

我现在已将 RestController 扩展到 CustomRestController 并添加了

'controller_class' => CustomRestController::class

到配置文件。

现在,var_dump($event->getRouteMatch()); null 在资源类中。

public function onBootstrap(MvcEvent $e)中,使用

$eventManager->attach(
    MvcEvent::EVENT_ROUTE, 
    function($e) {
        // I can still read `$e->getRouteMatch()->getParams()`
    } 
);

非常感谢任何有关如何处理此问题的建议。

更新答案

根本问题是RestParametersListener。它使用 FQCN,例如:

$listener = $events->attach(
    RestController::class,
    // more params
);

所以扩展 RestController 会导致这些 attach/detach 调用来避免使用新控制器。

一个干净的修复是将 RestParametersListener 扩展到 CustomRestParametersListener 并更改内部控制器 类。

扩展后,我还在 module.config.php 中添加了它:

'service_manager' => [
    'invokables' => [
        'ZF\Rest\RestParametersListener' => CustomRestParametersListener::class,
    ],
    // ...
]

初步回答:

在 zf-rest 开发团队修复问题 102 和 103 之前找到解决方法

在我的 CustomRestController:

try {
    $this->manuallyInjectRouteMatch(); // added this line
    $value = $this->getResource()->create($data);
} catch (Throwable $e) {
    return $this->createApiProblemFromThrowable($e);
} catch (Exception $e) {
    return $this->createApiProblemFromException($e);
}

其中:

/**
 * By using this factory instead of the default one and by creating a CastorRestController
 * instead of RestController, the routeMatch property is "lost".
 * Manually injecting it so we have access to it inside the *Resource class
 */
private function manuallyInjectRouteMatch()
{
    $r = new \ReflectionProperty(Resource::class, 'routeMatch');
    $r->setAccessible(true);
    $r->setValue($this->getResource(), $this->getEvent()->getRouteMatch());
}

此外,manuallyInjectRouteMatch 也需要为其他 REST 方法调用