dogado-group / json-api-common

Common php interfaces and classes which represent the JSON:API protocol in order to build a client or server application.
https://www.dogado.de
MIT License
1 stars 0 forks source link

Pull additional route parameters out of the JSON API request object #18

Closed chris-doehring closed 3 years ago

chris-doehring commented 3 years ago

When designing RESTful API's you often want to use url's with additional context like this:

https://api.local/v1/customer/{customerId}/invoice/{invoiceId}

The current JSON API request makes it hard to pull out all named route parameters before the json api request part of the URL starts. There should be an easy to use mechanism to fetch named route parameters from the request, in addition to the existing id method. Without having that feature, one has to find a workaround to bypass the application default request object to the request handler without using the default json api tools.

chris-doehring commented 3 years ago

After looking into this, I came to the conclusion to not implement a new default mechanism to manage route parameters or any other additional request features, since most of it is framework dependent and therefor depends on the requirements of the implementation. Instead, we can include any custom objects or parameters when initializing the request handler classes in the json api server scenario. Let's try a Laravel implementation as demo:

/** @var \Psr\Http\Message\RequestInterface $psrRequest*/
$jsonApiRequest = JsonApiRequest::createFromHttpRequest(
    $psrRequest,
    $this->server->createRequestBody($psrRequest->getBody()->getContents()),
    null
);

/** @var \Illuminate\Http\Request $request */
foreach (config('jsonApi.handler') as $type => $handlerClass) {
    $handler = new $handlerClass();
    if ($handler instanceof AbstractCustomRequestHandler) {
        $handler->setLaravelRequest($request);
    }
    $this->server->addHandler($type, $handler);
}

In the above example I would create a custom AbstractRequestHandler which would either include a custom constructor parameter for the Laravel request or a setter. Using that pattern, we can inject any custom parameter into the request handler. However, to reduce the memory load which is required to hold all instantiated request handler classes, while only one of them is needed to handle the request, it would be good if the addHandler method would support callables, so only the used request handlers would be instantiated when needed. I will create a follow up for that feature request.