2017-02-27 38 views
1

所以我想讓用戶在向服務器運行一個休息API請求時請求.xml或者.json響應。 (很像twitter)基於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

考慮使用值的Accept請求的HTTP標頭,而不是URI末尾的文件擴展名。

我會說使用頭是更可靠和更「適當」的方式來確定數據應返回的格式。 URI應該用來指向特定的資源。 Accept頭文件應該由客戶端發送,告訴你應該返回什麼格式的數據。 除了成爲實現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'); 
    } 
} 

這個類是一個回調的路線的一個例子。這樣的實現允許您輕鬆擴展支持的格式列表而不會篡改路由。

+0

我已經使用Slim不應該苗條的框架能夠做到這一點? – RussellHarrower

+0

據我所知,Slim本身不能進行內容協商。 –