使用我自己的Laravel API

时间:2013-05-13 11:12:27

标签: php api rest laravel laravel-4

我正在开发一个Laravel 4应用程序,它将通过JSON REST API和Web UI对我的数据集进行相同的CRUD操作。似乎是为了防止破坏DRY原则,即我的UI应该使用我自己的API,将所有请求从UI路由回API。我不确定这项工作的最佳方法。据推测,我会有单独的UI和API控制器,并以某种方式路由请求。或者我应该完全看待不同的方法吗?

感谢。

7 个答案:

答案 0 :(得分:46)

我实际上是在修改相同的想法而且非常整洁。使用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 :(得分:24)

注意:正如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 w / cookies

$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的输入/ Cookie外观,请将输入/ Cookie外观替换为您自己的内容。

答案 2 :(得分:14)

Taylor Otwell suggested使用app()->handle()而不是Route::dispatch()来获得干净的请求。

对于Route::dispatch($request),我注意到非GET请求的端点(HTTP请求主体上的参数)是否使用依赖注入\Illuminate\Http\Request\Illuminate\Foundation\Http\FormRequest扩展实例,参数状态,cookie,文件等来自原始 HTTP请求。即,对于您的应用程序的控制器操作方法。

如果app控制器和API控制器的参数名称和post方法类型相同,则不会发现差异,因为传递了原始参数值。但是,当您手动汇编Request::create()的第3个参数时,Route::dispatch()将导致其被忽略。

app()->handle()修复了Laravel请求生命周期中的上下文问题。

警告: app()->handle()影响Illuminate\Support\Facades\Request,使用此新请求实例刷新它。作为连锁效应,在Request::isXmlHttpRequest()之后调用的redirect()->back()app()->handle()等调用将导致不可预测的行为。我建议您跟踪原始请求的上下文,然后使用redirect()->to(route('...')),以便严格控制应用的流量和状态。

鉴于所有这些极端情况,最好只使用Guzzle HTTP client进行手动卷曲。

答案 3 :(得分:3)

如果您正在使用自己的API,请使用app()->handle()代替Route::dispatch(),正如Derek MacDonald建议的那样。

app()->handle()创建一个新请求,而Route::dispatch()在堆栈中运行路由,有效地忽略属于您发送的请求的参数。

编辑:只是一个单挑。泰勒奥特威尔advises against using sub-requests to make internal API calls, as they mess the current route。您可以使用Guzzle之类的HTTP API客户端来进行API调用。

答案 4 :(得分:1)

您可以使用Optimus API consumer,API简洁明了,例如发出内部请求:

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

在它的核心,它使用Illuminate\Routing\RouterIlluminate\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));

答案 5 :(得分:1)

如果您要在内部使用护照登录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();
}

答案 6 :(得分: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();
}