2017-02-27 9 views
1

したがって、サーバーに残りのAPIリクエストを実行するときにユーザーが.xmlまたは.json応答を要求できるようにします。URLに基​​づいたスリムで異なるレスポンスタイプ

しかし、私は重複したコードを意味するので、以下の方法が.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)); 
    }); 

OR

// 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'])); 

}); 

誰もがこれを行う方法を知っていれば、それは素晴らしいことです。

答えて

0

URIの末尾にファイル拡張子の代わりにAccept要求のHTTPヘッダーの値を使用することを検討してください。

私は、ヘッダーを使用するとデータが返される形式を決定するより信頼性が高く、より適切な方法であると言います。 特定のリソースを指すためにURIを使用する必要があります。 Acceptヘッダをクライアントから送信して、どの形式のデータを返すべきかを教えてください。 RESTfulなサービスを実装する標準的な方法とは別に、(2番目の例のように)経路変更の頭痛を取り除きます。

このような実装に同意する場合は、問題を解決するために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'); 
    } 
} 

このクラスは、ルートへのコールバックの一例です。このような実装では、経路を改ざんすることなく、サポートされているフォーマットのリストを簡単に拡張することができます。

+0

私はすでにSlimを使用していますが、これを行うことができるスリムなフレームワークではありませんか? – RussellHarrower

+0

私が知る限り、Slimはコンテンツネゴシエーションを単独で行うことはできません。 –

関連する問題