【问题标题】:You can have your API and eat (consume) it in Laravel?你可以拥有你的 API 并在 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 个模型。当心成功。

标签: laravel api laravel-5


【解决方案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是无状态的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2012-04-09
    • 1970-01-01
    • 2021-04-11
    • 2016-10-31
    • 1970-01-01
    • 2015-12-24
    相关资源
    最近更新 更多