消费我自己的Laravel API
我正在开发一个Laravel 4应用程序,它将通过JSON REST API和Web UI对我的数据集进行相同的CRUD操作。 看来,为了防止打破DRY的原则,我的用户界面应该消耗我自己的API通过路由从UI的所有请求回到API。 我不确定这个工作的最佳方法。 据推测,我会分开的用户界面和API控制器,并以某种方式路由请求通过。 或者我应该一起看一个不同的方法?
谢谢。
我实际上正在修改相同的想法,它非常整齐。 有了Laravel,你就有能力做出内部请求(有些人可能把这个称为HMVC,但我不会)。 这是一个内部请求的基础知识。
$request = Request::create('/api/users/1', 'GET'); $response = Route::dispatch($request);
$response
现在将包含API返回的响应。 通常,这将返回一个JSON编码的string,这对客户端来说很好,但对于一个内部API请求来说并不好。 你将不得不在这里扩展一些东西,但基本上这个想法是返回实际的对象为内部调用,外部请求返回格式化的JSON响应。 你可以在这里使用诸如$response->getOriginalContent()
这样的东西。
你应该看看做的是构造某种内部的Dispatcher
,它允许你调度API请求并返回原始对象。 调度员还应该处理格式错误的请求或不良响应,并抛出exception匹配。
这个想法本身是可靠的。 但是规划一个API是很困难的。 我build议你写出所有预期端点的好列表,然后起草几个API版本,然后select最好的一个。
注意:正如vcardillo指出的那样,这些方法不会调用路由filter。
我现在正在做同样的事情,Jason的回答让我朝着一个很好的方向前进。 看看Symfony \ Component \ HttpFoundation \ Request文档,我想出了如何POST,以及我需要做的一切。 假设你正在使用一个表单,下面是一些可以帮助你的代码:
得到:
$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 w / cookies
$request = Request::create('/api/users/1', 'POST', Input::get(), Cookie::get('name')); $response = Route::dispatch($request);
POST w /文件
$request = Request::create('/api/users/1', 'POST', Input::get(), null, Input::file('file')); $response = Route::dispatch($request);
我希望这可以帮助别人。 如果您不使用表单,或者您没有使用Laravel的Input / Cookie外观,请用您自己的内容replaceInput / Cookie外观。
Taylor Otwell build议使用app()->handle()
而不是Route::dispatch()
来实现一个干净的请求。
对于Route::dispatch($request)
我注意到,如果非GET请求的端点(HTTP请求体上的参数)使用注入的\Illuminate\Http\Request
或\Illuminate\Foundation\Http\FormRequest
扩展实例的\Illuminate\Foundation\Http\FormRequest
,参数的状态,cookies,文件等来自原始的 HTTP请求。 即为您的应用程序的控制器操作方法。
如果您的应用程序控制器和API控制器的参数名称和发布方法types相同,您将不会注意到由于传递原始参数值而产生的差异。 但是当你手动组装Request::create()
的第三个参数时, Route::dispatch()
会导致它被忽略。
app()->handle()
修复了Laravel请求生命周期中的上下文问题。
警告: app()->handle()
影响Illuminate\Support\Facades\Request
,使用这个新的请求实例刷新它。 作为一种连锁效应,在app()->handle()
之后调用Request::isXmlHttpRequest()
或者redirect()->back()
app()->handle()
会导致不可预知的行为。 我build议跟踪原始请求的上下文,而是使用redirect()->to(route('...'))
以便严格控制应用程序的stream程和状态。
鉴于所有这些angular落的情况下,最好是使用Guzzle HTTP客户端进行手动curl。
如果您正在使用自己的API,请使用app()->handle()
代替Route::dispatch()
正如Derek MacDonald所build议的那样。
app()->handle()
创build一个新的请求,而Route::dispatch()
在堆栈内运行路由,有效地忽略了发送请求的一部分参数。
编辑 :只是一个单挑。 泰勒Otwell build议反对使用子请求进行内部的API调用,因为他们搅乱了当前的路线 。 你可以像一个HTTP API客户端,而不是做API调用。
您可以使用Optimus API使用者 ,API清晰且简单,例如发出内部请求:
$response = app()->make('apiconsumer')->post('/oauth/token', $data);
在它的核心,它使用Illuminate\Routing\Router
和Illuminate\Http\Request
来打电话
// create the request $this->request->create($uri, $method, $data, [], [], $server, $content); // get the response $response = $this->router->prepareResponse($request, $this->app->handle($request));
如果您在内部使用护照loginapi,则需要将参数添加到原始请求中:
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(); }
如果您在内部使用护照loginapi,则需要将参数添加到原始请求中:
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(); }