一個API的功能主要是擷取請求並返迴響應給用戶端,響應的格式是多樣的,比如JSON,返迴響應的方式也是多樣的,這取決於當前構建的API的複雜度以及對未來的考量。
返迴響應最簡單的方式是直接從控制器返回數組或對象,但不是每個響應對象都能保證格式正確,所以你要確保它們實現了 ArrayObject或者 Illuminate\Support\Contracts\ArrayableInterface介面:
class UserController{ public function index() { return User::all(); }}
在本例中, User類繼承自 Illuminate\Database\Eloquent\Model,這意味著返回的是可以被格式化為數組的資料,當然也可以返回單個使用者:
class UserController{ public function show($id) { return User::findOrFail($id); }}
Dingo API會自動將響應格式化為JSON格式並設定 Content-Type頭為 application/json。
1、響應構建器
響應構建器提供了平滑的介面以便我們輕鬆構建更多自訂的響應。響應構建器通常與轉換器(Transformer)一起使用。
要使用響應構建器控制器需要使用 Dingo\Api\Routing\Helperstrait,為了讓每個控制器都可以使用這個trait,我們將其放置在API基類控制器 Controller中:
use Dingo\Api\Routing\Helpers;use Illuminate\Routing\Controller;class BaseController extends Controller{ use Helpers;}
現在可以定義一個繼承自該控制器的控制器,在這些控制器中可以通過 $response屬性來訪問響應構建器。
數組響應
class UserController extends BaseController{ public function show($id) { $user = User::findOrFail($id); return $this->response->array($user->toArray()); }}
單個Item響應
class UserController extends BaseController{ public function show($id) { $user = User::findOrFail($id); return $this->response->item($user, new UserTransformer); }}
集合響應
class UserController extends BaseController{ public function index() { $users = User::all(); return $this->response->collection($users, new UserTransformer); }}
分頁響應
class UserController extends BaseController{ public function index() { $users = User::paginate(25); return $this->response->paginator($users, new UserTransformer); }}
無內容響應
return $this->response->noContent();
建立響應
return $this->response->created();
還可以將位置資訊作為建立資源的第一個參數:
return $this->response->created($location);
錯誤響應
你可以使用多種內建錯誤建置錯誤響應:
// A generic error with custom message and status code.return $this->response->error('This is an error.', 404);// A not found error with an optional message as the first parameter.return $this->response->errorNotFound();// A bad request error with an optional message as the first parameter.return $this->response->errorBadRequest();// A forbidden error with an optional message as the first parameter.return $this->response->errorForbidden();// An internal error with an optional message as the first parameter.return $this->response->errorInternal();// An unauthorized error with an optional message as the first parameter.return $this->response->errorUnauthorized();
添加額外的回應標頭
使用了上述方法之後還可以通過添加回應標頭來自訂響應:
return $this->response->item($user, new UserTransformer)->withHeader('X-Foo', 'Bar');
添加中繼資料
某些轉化層可能會使用中繼資料(meta data),這在你需要提供額外與資源關聯的資料時很有用:
return $this->response->item($user, new UserTransformer)->addMeta('foo', 'bar');
還可以設定中繼資料數組替代多個方法鏈的調用:
return $this->response->item($user, new UserTransformer)->setMeta($meta);
設定響應狀態代碼
return $this->response->item($user, new UserTransformer)->setStatusCode(200);
2、自訂響應格式
在安裝配置中我們已經簡單接觸過響應格式,預設情況下Dingo API會自動使用JSON格式並設定相應的 Content-Type頭。除了JSON之外還有一個JSONP格式,改格式會將響應封裝到一個回調中。要註冊改格式只需要簡單將設定檔(Laravel)或開機檔案(Lumen)中的預設JSON格式替換成JSONP即可:
'formats' => [ 'json' => 'Dingo\Api\Http\Response\Format\Jsonp']
或者:
Dingo\Api\Http\Response::addFormatter('json', new Dingo\Api\Http\Response\Format\Jsonp);
預設情況下回調參數預設查詢字串是callback,這可以通過修改建構函式的第一個參數來設定。如果查詢字串不包含任何參數將會返回JSON響應。
你還可以註冊並使用自己需要的響應格式,自訂的格式對象需要繼承自 Dingo\Api\Http\Response\Format\Format類,同時還要實現如下這些方法: formatEloquentModel, formatEloquentCollection, formatArray以及 getContentType。
3、Morphing 和 Morphed事件
在Dingo API發送響應之前會先對該響應進行轉化(morph),這個過程包括運行所有轉換器(Transformer)以及通過配置的響應格式發送響應。如果你需要控制響應如何被轉化可以使用 ResponseWasMorphed和 ResponseIsMorphing事件。
我們在 app/Listeners中為事件建立監聽器:
use Dingo\Api\Event\ResponseWasMorphed;class AddPaginationLinksToResponse{ public function handle(ResponseWasMorphed $event) { if (isset($event->content['meta']['pagination'])) { $links = $event->content['meta']['pagination']['links']; $event->response->headers->set( 'link', sprintf('<%s>; rel="next", <%s>; rel="prev"', $links['links']['next'], $links['links']['previous']) ); } }}
然後通過在 EventServiceProvider中註冊事件及其對應監聽器來監聽該事件:
protected $listen = [ 'Dingo\Api\Event\ResponseWasMorphed' => [ 'App\Listeners\AddPaginationLinksToResponse' ]];
現在所有包含分頁連結的響應也會將這些連結添加到 Link頭。
注意:目前該功能還在開發階段,不建議用於生產環境。