php 使用我自己的 Laravel API
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16520691/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Consuming my own Laravel API
提问by robjmills
I'm developing a Laravel 4 app that will make the same CRUD operations on my dataset available through a JSON REST API and a Web UI. It seems that to prevent breaking the DRY principle that my UI should consume my own API by routing all requests from the UI back to the API. I'm unsure though about the best approach to making this work. Presumably I would have separate UI and API controllers and somehow route the requests through. Or should I be looking at a different approach altogether?
我正在开发一个 Laravel 4 应用程序,它将通过 JSON REST API 和 Web UI 对我的数据集进行相同的 CRUD 操作。似乎是为了防止打破 DRY 原则,即我的 UI 应该通过将所有请求从 UI 路由回 API 来使用我自己的 API。我不确定使这项工作的最佳方法。大概我会有单独的 UI 和 API 控制器,并以某种方式路由请求。还是我应该完全考虑不同的方法?
Thanks.
谢谢。
采纳答案by Jason Lewis
I'm actually tinkering with the same idea and it's pretty neat. With Laravel you do have the ability to make internal requests (some might refer to this as HMVC, but I won't). Here's the basics of an internal request.
我实际上正在修补相同的想法,它非常整洁。使用 Laravel,您确实可以发出内部请求(有些人可能将其称为 HMVC,但我不会)。这是内部请求的基础知识。
$request = Request::create('/api/users/1', 'GET');
$response = Route::dispatch($request);
$response
will now contain the returned response of the API. Typically this will be returned a JSON encoded string which is great for clients, but not that great for an internal API request. You'll have to extend a few things here but basically the idea is to return the actual object back through for the internal call, and for external requests return the formatted JSON response. You can make use of things like $response->getOriginalContent()
here for this kind of thing.
$response
现在将包含 API 的返回响应。通常,这将返回一个 JSON 编码的字符串,这对客户端来说很好,但对内部 API 请求来说不是很好。你必须在这里扩展一些东西,但基本上这个想法是为内部调用返回实际对象,对于外部请求返回格式化的 JSON 响应。你可以利用像$response->getOriginalContent()
这里这样的东西来做这种事情。
What you should look at doing is constructing some sort of internal Dispatcher
that allows you to dispatch API requests and return the original object. The dispatcher should also handle malformed requests or bad responses and throw exceptions to match.
您应该考虑构建某种内部结构Dispatcher
,允许您分派 API 请求并返回原始对象。调度程序还应该处理格式错误的请求或错误的响应并抛出异常以进行匹配。
The idea itself is solid. But planning an API is hard work. I'd recommend you write up a good list of all your expected endpoints and draft a couple of API versions then select the best one.
这个想法本身是可靠的。但是规划 API 是一项艰巨的工作。我建议您编写一份所有预期端点的清单并起草几个 API 版本,然后选择最好的一个。
回答by Domenic Fiore
NOTE: As vcardillo pointed out below, route filters are not called with these methods.
注意:正如 vcardillo 在下面指出的,这些方法不会调用路由过滤器。
I am currently doing the same thing, and Jason's answer got me going in a great direction. Looking at the Symfony\Component\HttpFoundation\Requestdocumentation, I figured out how to POST, as well as everything else I'd need to do. Assuming you're using a form, here is some code that could help you:
我目前正在做同样的事情,杰森的回答让我朝着一个很好的方向前进。查看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 w/ cookies
使用 cookie 发布
$request = Request::create('/api/users/1', 'POST', Input::get(), Cookie::get('name'));
$response = Route::dispatch($request);
POST w/ files
POST 带文件
$request = Request::create('/api/users/1', 'POST', Input::get(), null, Input::file('file'));
$response = Route::dispatch($request);
I hope this helps someone else. If you aren't using a form, or you are but not using Laravel's Input / Cookie facade, replace the Input / Cookie facades with your own content.
我希望这对其他人有帮助。如果你没有使用表单,或者你没有使用 Laravel 的 Input / Cookie 门面,请用你自己的内容替换 Input / Cookie 门面。
回答by Derek MacDonald
Taylor Otwell suggestedusing app()->handle()
rather than Route::dispatch()
to achieve a clean request.
Taylor Otwell建议使用app()->handle()
而不是Route::dispatch()
实现干净的要求。
For Route::dispatch($request)
I noticed if the endpoint of your non-GET request (parameters on the HTTP request body) uses a dependency injected \Illuminate\Http\Request
or \Illuminate\Foundation\Http\FormRequest
extending instance, state of the parameters, cookies, files, etc. are from the originalHTTP request. i.e., for your application's controller action method.
因为Route::dispatch($request)
我注意到如果您的非 GET 请求的端点(HTTP 请求正文上的参数)使用依赖项注入\Illuminate\Http\Request
或\Illuminate\Foundation\Http\FormRequest
扩展实例,参数、cookie、文件等的状态来自原始HTTP 请求。即,对于您的应用程序的控制器操作方法。
If parameter names and post method type for your app controller and API controller are the same, you won't notice the difference since the original parameter values are passed on. But when you're manually assembling the 3rd parameter of Request::create()
, Route::dispatch()
will result in it being ignored.
如果您的应用程序控制器和 API 控制器的参数名称和 post 方法类型相同,您将不会注意到差异,因为原始参数值被传递。但是当您手动组装 的第三个参数时Request::create()
,Route::dispatch()
将导致它被忽略。
app()->handle()
fixes that context problem in the Laravel request lifecycle.
app()->handle()
修复了 Laravel 请求生命周期中的上下文问题。
Caveat:app()->handle()
affects Illuminate\Support\Facades\Request
, refreshing it with this new request instance. As a knock-on effect, calls like Request::isXmlHttpRequest()
or redirect()->back()
invoked after app()->handle()
will cause unpredictable behaviour. I'd suggest tracking the context of your original request and instead use redirect()->to(route('...'))
so you strictly control flow and state of your app.
警告:app()->handle()
影响 Illuminate\Support\Facades\Request
,用这个新的请求实例刷新它。作为连锁效应,调用 likeRequest::isXmlHttpRequest()
或redirect()->back()
调用 afterapp()->handle()
将导致不可预测的行为。我建议跟踪您原始请求的上下文并改为使用,redirect()->to(route('...'))
以便您严格控制应用程序的流程和状态。
Given all these corner cases, it may be best to just do a manual curl using a Guzzle HTTP client.
鉴于所有这些极端情况,最好仅使用Guzzle HTTP 客户端进行手动卷曲。
回答by Pankaj Garg
If you are looking for using passport login api internally, then you need to add the parameters to original request:
如果您正在寻找在内部使用护照登录 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();
}
回答by jpcaparas
If you're consuming your own API, use app()->handle()
instead of Route::dispatch()
as Derek MacDonald has suggested.
如果您正在使用自己的 API,请使用Derek MacDonald 建议的app()->handle()
代替Route::dispatch()
。
app()->handle()
creates a fresh request, while Route::dispatch()
runs the route within the stack, effectively ignoring parameters that are part of the request that you're sending.
app()->handle()
创建一个新的请求,同时Route::dispatch()
在堆栈中运行路由,有效地忽略作为您发送的请求的一部分的参数。
Edit: Just a heads-up. Taylor Otwell advises against using sub-requests to make internal API calls, as they mess the current route. You can an HTTP API client like Guzzle
instead to make the API calls.
编辑:只是一个提示。Taylor Otwell建议不要使用子请求进行内部 API 调用,因为它们会干扰当前路由。您可以使用 HTTP API 客户端Guzzle
来代替进行 API 调用。
回答by Pankaj Garg
If you are looking for using passport login api internally, then you need to add the parameters to original request:
如果您正在寻找在内部使用护照登录 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();
}
回答by Walid Ammar
You can use Optimus API consumer, the API is clean and simple, example making an internal request:
您可以使用Optimus API consumer,API 干净简单,例如发出内部请求:
$response = app()->make('apiconsumer')->post('/oauth/token', $data);
In it's core, it uses Illuminate\Routing\Router
and Illuminate\Http\Request
to make the call
在它的核心中,它使用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));