流明中的反向路由

As REST API developer, in need to test my application. I recently moved to the OpenAPI specification, and I really want to test my API responses against it. My application is based on Lumen.

While routes with no path parameters cause no problem, I'm facing a "reverse routing" problem. For example, in my functional tests, I'm testing the route: GET /themes/{themeId}/questions, which should return the questions related to the theme number themeId.

The actual URI may be something like /themes/17/questions. The problem is that I need to find the exact pattern with {params} in order to test my API against the specification. To be clear, I need a way to :

/themes/17/questions => /themes/{themeId}/questions

I already found some kind of solution, but I'm absolutely not satisfied and it feels really messy:

/**
 * Get the OpenAPI URI based on the actual request URI.
 *
 * @param string $method The HTTP method (GET, POST, PUT, PATCH, DELETE etc.)
 * @param string $actualUri The actual request URI
 *
 * @return string
 */
public function getOpenAPIUri(string $method, $actualUri)
{
    $currentRouter = $this->dispatch($method, $actualUri); // Calls the Lumen dispatcher

    $filteredRoutes = Collection::make($this->app->router->getRoutes())
        // Reject routes which do not match the method
        ->reject(function ($routeData, $routeKey) use ($method) {
            return !Str::startsWith($routeKey, strtoupper($method));
        })
        // Reject routes which do not match the controller/action
        ->reject(function ($routeData) use ($currentRouter) {
            if (!isset($routeData["action"]["uses"])) {
                return true;
            }

            return $currentRouter[1]["uses"] !== $routeData["action"]["uses"];
        })
        // Reject routes which have not the same amount of parts (splitted by "/")
        ->reject(function ($routeData) use ($actualUri) {
            $actualParts = explode("/", trim($actualUri, "/"));
            $routeParts = explode("/", trim($routeData["uri"], "/"));
            return count($actualParts) !== count($routeParts);
        })
        // Reject routes which does not have the same arguments
        ->reject(function ($routeData, $routeKey) use ($currentRouter) {
            $pattern = "/{([a-zA-Z]+):[a-zA-Z0-9\/\\\+\-_\[\]\*\{\}\|\.\^]+}/";
            $strippedUri = preg_replace($pattern, '{$1}', $routeKey);

            $paramKeys = Collection::make(array_keys($currentRouter[2]))->map(function ($param) {
                return "{{$param}}";
            });

            return !Str::contains($strippedUri, $paramKeys->toArray());
        });

    if ($filteredRoutes->isEmpty()) {
        return $actualUri;
    } else {
        $match = $filteredRoutes->first();

        return $match["uri"];
    }
}

Any suggestion would be greatly appreciated!