2013-05-13 55 views
46

我正在開發一個Laravel 4應用程序,它將通過JSON REST API和Web UI對我的數據集進行相同的CRUD操作。看起來,爲了防止打破DRY原則,我的UI應該通過將所有請求從UI返回給API來使用我自己的API。儘管如此,我仍然不確定如何做這項工作的最佳方法。據推測,我會分開UI和API控制器,並以某種方式路由請求。或者我應該完全看待不同的方法?消費我自己的Laravel API

謝謝。

回答

37

我實際上正在修改相同的想法,它非常整齊。有了Laravel,你確實有能力提出內部請求(有些人可能將此稱爲HMVC,但我不會)。以下是內部請求的基礎知識。

$request = Request::create('/api/users/1', 'GET'); 

$response = Route::dispatch($request); 

$response現在將包含返回的API響應。通常,這將返回一個JSON編碼的字符串,這對客戶端來說很好,但對於內部API請求來說並不好。你必須在這裏擴展一些東西,但基本上這個想法是爲內部調用返回實際的對象,而爲外部請求返回格式化的JSON響應。你可以在這裏使用諸如$response->getOriginalContent()這樣的東西來做這種事情。

你應該看看做的是構造某種內部Dispatcher,它允許你調度API請求並返回原始對象。調度員還應該處理格式錯誤的請求或不良響應,並拋出異常匹配。

這個想法本身是可靠的。但是規劃一個API是很困難的。我建議你寫出所有預期端點的良好列表並起草幾個API版本,然後選擇最好的一個。

+1

有趣的是,我在找這方面的文檔,最初找不到任何。意識到這實際上是從Symfony繼承的 – robjmills 2013-05-14 10:05:07

+0

是的創建初始請求是通過Symfony'HttpFoundation'組件完成的,但是請求的分派是由路由器完成的。 – 2013-05-14 10:19:21

+0

你提到「原始對象」,你在這裏指的是什麼? – robjmills 2013-05-14 10:49:21

20

注意:正如vcardillo指出的那樣,路由過濾器不會用這些方法調用。

我目前正在做同樣的事情,賈森的回答讓我朝着一個很好的方向前進。看着Symfony\Component\HttpFoundation\Request文檔,我想出瞭如何POST,以及我需要做的一切。您使用的是形式假設,這裏是一些代碼,可以幫助你:

GET:

$request = Request::create('/api/users/1', 'GET'); 

$response = Route::dispatch($request); 

POST:

$request = Request::create('/api/users/1', 'POST', Input::get()); 

$response = Route::dispatch($request); 

POST瓦特/餅乾

$request = Request::create('/api/users/1', 'POST', Input::get(), Cookie::get('name')); 

$response = Route::dispatch($request); 

POST w/files

$request = Request::create('/api/users/1', 'POST', Input::get(), null, Input::file('file')); 

$response = Route::dispatch($request); 

我希望這可以幫助別人。如果您沒有使用表單,或者您沒有使用Laravel的Input/Cookie外觀,請用您自己的內容替換Input/Cookie外觀。

+0

完美,謝謝! – Ulterior 2014-09-23 21:49:49

+2

我所看到的唯一問題就是沒有調用路由過濾器。 – vcardillo 2015-01-24 18:44:50

+0

鏈接中斷,更新:http://api.symfony.com/master/Symfony/Component/HttpFoundation/Request.html – 2016-01-18 07:54:26

10

泰勒Otwell suggested使用app()->handle()而不是Route::dispatch()實現一個乾淨的請求。

對於Route::dispatch($request)我注意到,如果你的非GET請求的終點(在HTTP請求的身體參數)使用依賴注入\Illuminate\Http\Request\Illuminate\Foundation\Http\FormRequest延長例如,參數,餅乾,文件等的狀態是從原始 HTTP請求。即爲您的應用程序的控制器操作方法。

如果您的應用程序控制器和API控制器的參數名稱和發佈方法類型相同,您將不會注意到因傳遞原始參數值而產生的差異。但是當您手動組裝Request::create()的第三個參數時,Route::dispatch()將導致它被忽略。

app()->handle()修復了Laravel請求生命週期中的上下文問題。

注意:app()->handle()影響Illuminate\Support\Facades\Request,使用這個新的請求實例刷新它。作爲連鎖效應,在app()->handle()之後調用Request::isXmlHttpRequest()redirect()->back()等調用將導致不可預知的行爲。我建議跟蹤原始請求的上下文,並改爲使用redirect()->to(route('...')),以便嚴格控制應用的流量和狀態。

鑑於所有這些情況,最好使用Guzzle HTTP client進行手動捲曲。

0

您可以使用Optimus API consumer,API是乾淨和簡單,例如使內部請求:在它的核心,它採用Illuminate\Routing\RouterIlluminate\Http\Request撥打電話

$response = app()->make('apiconsumer')->post('/oauth/token', $data); 

// create the request 
$this->request->create($uri, $method, $data, [], [], $server, $content); 

// get the response 
$response = $this->router->prepareResponse($request, $this->app->handle($request)); 
1

如果您正在使用自己的API,請使用app()->handle()而不是Route::dispatch(),正如Derek MacDonald所建議的。

app()->handle()創建一個新的請求,而Route::dispatch()在堆棧內運行路由,有效地忽略了參數,這些參數是您要發送的請求的一部分。

編輯:只是單挑。泰勒Otwell advises against using sub-requests to make internal API calls, as they mess the current route。您可以使用HTTP API客戶端(例如Guzzle)來進行API調用。

0

如果您正在尋找內部使用護照登錄API,那麼你需要的參數添加到原來的請求:

protected function manualLogin(Request $request) 
{ 
    $email = $request->input('email'); 
    $password = $request->input('password'); 

    $request->request->add([ 
     'username' => $email, 
     'password' => $password, 
     'grant_type' => 'password', 
     'client_id' => $clientID, 
     'client_secret' => $clientSecret, 
     'scope' => '*']); 

    $newRequest = Request::create('/oauth/token', 'post'); 

    return Route::dispatch($newRequest)->getContent(); 
} 
0

如果您正在尋找內部使用護照登錄API,那麼你需要添加參數原始請求:

protected function manualLogin(Request $request) 
    { 
     $email = $request->input('email'); 
     $password = $request->input('password'); 

     $request->request->add([ 
     'username' => $email, 
     'password' => $password, 
     'grant_type' => 'password', 
     'client_id' => $clientID, 
     'client_secret' => $clientSecret, 
     'scope' => '*']); 

    $newRequest = Request::create('/oauth/token', 'post'); 

    return Route::dispatch($newRequest)->getContent(); 
}