基于 url 的苗条和不同的响应类型
Slim and different response type based on url
所以我想允许用户在 运行 向服务器发出休息 API 请求时请求 .xml 或 .json 响应。 (很像推特)
但我不认为下面的方法是最好的方法,因为它意味着重复代码,肯定有更好的方法来允许 .xml 或 .json 响应。
$app->get('/books/:id.xml', function ($id) use ($app) {
$app->render('/xml/books.xml', array('id' => $id));
});
$app->get('/books/:id.json', function ($id) use ($app) {
$app->render('json/books.json', array('id' => $id));
});
或
// Define app routes
$app->get('/hello/{name}.{type}', function ($request, $response, $args) {
//return $response->write("Hello " . $args['name']);
if($args['type'] == 'xml')
{
return 'this is xml';
}
var_dump(parse_url($_SERVER['REQUEST_URI']));
});
如果有人知道如何做到这一点,那就太好了。
考虑在 URI 末尾使用请求的 Accept
HTTP header 的值而不是文件扩展名。
我想说使用 header 更可靠,也更 "proper" 确定数据返回格式的方法。
URI 应该用来指向特定的资源。 Accept
header 应该是客户端发来的,告诉你返回的数据是什么格式。
除了作为实现 RESTful 服务的标准方式之外,它还消除了更改路由的麻烦(就像在您的第二个示例中一样)。
如果您同意这样的实施方式,excellent library可以解决您的问题。
它有很多用途,这里是您的用例示例:
<?php
use Negotiation\Negotiator;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
class YourController
{
public function __construct(Negotiator $negotiator, DataProvider $someDataProvider)
{
$this->negotiator = $negotiator;
$this->someDataProvider = $someDataProvider;
}
/**
* Processing request.
*
* We get data, then we use Negotiator to detect what format the requestor prefers.
* Then we return data in requested format or in case format is not supported,
* fall back to JSON.
*
*
* @param Request $request
* @param Response $response
* @return Response
*/
public function __invoke(Request $request, Response $response)
{
$data = $this->someDataProvider->getSomeData();
$mediaType = $this->determineMediaType($request);
switch ($mediaType) {
case 'application/json':
default:
// $data = $data->asJson();
// transform data to JSON...
break;
case 'application/xml':
$data = $data->asXml();
// transform data to XML...
break;
}
// Write data to body of response
$response->getBody()->write($data);
// Set appropriate response header
return $response->withHeader('Content-Type', $mediaType);
}
/**
* Find preferred data format from Accept header.
*
* Uses Negotiator to determine whether JSON or XML should be returned.
*
* @param Request $request
* @return string
*/
private function determineMediaType(Request $request)
{
$acceptHeader = $this->extractAcceptHeader($request);
// Set list of "known" formats, i.e. formats that your service supports
$known = ['application/json', 'application/xml'];
// Let negotiator determine what format should be used
$mediaType = $this->negotiator->getBest($acceptHeader, $known);
if ($mediaType) {
return $mediaType->getValue();
} else {
return 'application/json'; # if request has unexpected value of accept header, default to JSON
}
}
/**
* Extract Accept header value from Request object
* @param Request $request
* @return string
*/
private function extractAcceptHeader(Request $request)
{
return $request->getHeaderLine('Accept');
}
}
此 class 是路由回调的示例。这样的实现使您可以轻松扩展支持的格式列表,而无需篡改路由。
所以我想允许用户在 运行 向服务器发出休息 API 请求时请求 .xml 或 .json 响应。 (很像推特)
但我不认为下面的方法是最好的方法,因为它意味着重复代码,肯定有更好的方法来允许 .xml 或 .json 响应。
$app->get('/books/:id.xml', function ($id) use ($app) {
$app->render('/xml/books.xml', array('id' => $id));
});
$app->get('/books/:id.json', function ($id) use ($app) {
$app->render('json/books.json', array('id' => $id));
});
或
// Define app routes
$app->get('/hello/{name}.{type}', function ($request, $response, $args) {
//return $response->write("Hello " . $args['name']);
if($args['type'] == 'xml')
{
return 'this is xml';
}
var_dump(parse_url($_SERVER['REQUEST_URI']));
});
如果有人知道如何做到这一点,那就太好了。
考虑在 URI 末尾使用请求的 Accept
HTTP header 的值而不是文件扩展名。
我想说使用 header 更可靠,也更 "proper" 确定数据返回格式的方法。
URI 应该用来指向特定的资源。 Accept
header 应该是客户端发来的,告诉你返回的数据是什么格式。
除了作为实现 RESTful 服务的标准方式之外,它还消除了更改路由的麻烦(就像在您的第二个示例中一样)。
如果您同意这样的实施方式,excellent library可以解决您的问题。
它有很多用途,这里是您的用例示例:
<?php
use Negotiation\Negotiator;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
class YourController
{
public function __construct(Negotiator $negotiator, DataProvider $someDataProvider)
{
$this->negotiator = $negotiator;
$this->someDataProvider = $someDataProvider;
}
/**
* Processing request.
*
* We get data, then we use Negotiator to detect what format the requestor prefers.
* Then we return data in requested format or in case format is not supported,
* fall back to JSON.
*
*
* @param Request $request
* @param Response $response
* @return Response
*/
public function __invoke(Request $request, Response $response)
{
$data = $this->someDataProvider->getSomeData();
$mediaType = $this->determineMediaType($request);
switch ($mediaType) {
case 'application/json':
default:
// $data = $data->asJson();
// transform data to JSON...
break;
case 'application/xml':
$data = $data->asXml();
// transform data to XML...
break;
}
// Write data to body of response
$response->getBody()->write($data);
// Set appropriate response header
return $response->withHeader('Content-Type', $mediaType);
}
/**
* Find preferred data format from Accept header.
*
* Uses Negotiator to determine whether JSON or XML should be returned.
*
* @param Request $request
* @return string
*/
private function determineMediaType(Request $request)
{
$acceptHeader = $this->extractAcceptHeader($request);
// Set list of "known" formats, i.e. formats that your service supports
$known = ['application/json', 'application/xml'];
// Let negotiator determine what format should be used
$mediaType = $this->negotiator->getBest($acceptHeader, $known);
if ($mediaType) {
return $mediaType->getValue();
} else {
return 'application/json'; # if request has unexpected value of accept header, default to JSON
}
}
/**
* Extract Accept header value from Request object
* @param Request $request
* @return string
*/
private function extractAcceptHeader(Request $request)
{
return $request->getHeaderLine('Accept');
}
}
此 class 是路由回调的示例。这样的实现使您可以轻松扩展支持的格式列表,而无需篡改路由。