你可以拥有你的 API 并在 Laravel 中吃(消费)它吗?

Posted

技术标签:

【中文标题】你可以拥有你的 API 并在 Laravel 中吃(消费)它吗?【英文标题】:You can have your API and eat (consume) it in Laravel? 【发布时间】:2017-07-04 04:03:09 【问题描述】:

我在 Laravel 中创建了一个返回 json 的 API。 (routes/api.php)

现在我想在项目的web 端使用上述 API(routes/web.php(包括中间件)、blade 视图 等) .

我目前的解决方案是这样的:

public function register(Request $request) 
    // password1 == password2 etc (form logic / validation)
    $internal_request = Request::create($this->base_api_url . 'register', 'POST');
    $internal_request->replace($request->input());
    $response = Route::dispatch($internal_request);

如果表单有效,它将请求“转发”到我的 api 的 api 对应方。但我觉得这不是真正的最佳实践或聪明。除了loginregister 之外的其他路由使用存储在会话中的api 令牌进行调用。他们将令牌“x-token”作为标题附加到$internal_request。在中间件中这样做会更好吗?是否有一些最佳实施的例子?

我的 API 有这样一个方法:

POST api/register 检查所需字段是否存在并具有 rigt 格式(验证)

我的网络路由有/register

这将首先检查密码是否与密码验证输入 (pass1 == pass2) 匹配,然后将其传递给等效的 api。

所以web 应该是api 的超集(验证方式)。

【问题讨论】:

专注于单一职责,然后分解共同的工作。 Web、CLI 和 API 负责解组和验证输入。一旦对输入感到满意,他们就会将经过验证的输入交给执行所需任务的公共服务。最后,他们获取该公共服务的结果并将其编组回给用户。像这样的环回调用可以工作,但它们是多余的,因为编组/解组发生了两次。它还使测试变得比必要的更加困难,因为您最终依赖于集成测试并且经常一遍又一遍地测试相同的路径。 @bishop 是的,我正在考虑在模型中做更多的事情,而在控制器中做更少的事情。这样模型=单一责任。但是有一些硬定义的方法吗? 不,由于 TIMTOWTDI,没有硬定义的方式。我同意将大部分工作推入模型服务层是可行的方法。但是,我强调服务部分:大量模型类型的类处理数据转换整体问题的不同部分,而不是一些做太多事情的巨大模型。 我没有这样做的一个原因是,laravel 的验证默认使用request 对象的方式,直观感觉就像:“在控制器中这样做”。我的项目相对较小,只有 您的项目现在有 10 个模型。当心成功。 【参考方案1】:

我想我会这样做:

在控制器中检测我们是否处理 API 请求或 Web 请求 检测相应的凭据(令牌或会话) 如果是 web 则做表单逻辑 在两种情况下都做 api 逻辑 相应地创建视图或 json 响应 都在同一个控制器中

【讨论】:

【参考方案2】:

据我了解您的问题,您希望对 api 和 web 请求应用相同的逻辑,您可能只想 (a) 验证 web 请求的表单和/或 (b) 将响应包装在 json 中API 请求。

我认为最好的方法是为 web 和 api 请求引用相同的控制器和方法,例如:

在你的 routes/web.php 中,添加Route::post('/register', 'RegistrationController@register);`

然后在你的 routes/api.php 中添加Route::post('/register', 'RegistrationController@register)`

所以最终两个请求(api/register 和 /register)都命中同一个控制器 和方法。

现在,在您的控制器中,您可以根据请求执行额外的操作,如下所示:

public function register(Request $request) 
    if(!$request->expectsJson())  // you may want to swap this with $request->isJson() depending on the HTTP headers for your app
        $this->validateWebRegistration($request); // your validation logic specific to web requests here
    

    // common logic here (including validation); store result as $result

    if($request->expectsJson())  // based on HTTP headers as above
        return response()->json($result);
     else 
        return view('register', $result);
    

【讨论】:

我将编辑我的问题,以便您更好地了解它们之间的区别:) 我已根据您更新的问题编辑了我的答案。我不明白你问题的第一部分。 x-token 是什么?您指的是 CSRF 令牌吗? X-token 是我在 api/login 上生成的 api 令牌,应该作为每个请求的标头发送。 如果它应该作为请求头发送,难道不应该是客户端而不是服务器的责任吗?如果您需要在成功登录时设置响应标头,您可以将该逻辑添加到您的登录控制器 嗯,我考虑过,但是 Web 有更多(超集)验证并与会话一起工作。 api是无状态的。

以上是关于你可以拥有你的 API 并在 Laravel 中吃(消费)它吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swoole 来加速你的 Laravel 应用

从数据库中检索数据并在 json laravel 4 中打印它们

laravel 在多行中插入数据,并在一个循环中从 API 获取 [关闭]

Laravel 中间件 API 认证

如何自定义 laravel api 的 json 响应并在 vuex 中显示它们

在使用第三方API并在Laravel中创建域时使用适配器模式