基于 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 是路由回调的示例。这样的实现使您可以轻松扩展支持的格式列表,而无需篡改路由。