【问题标题】:RESTful API: Data from multiple endpoints in one single viewRESTful API:一个视图中来自多个端点的数据
【发布时间】:2020-01-24 19:57:10
【问题描述】:

我已经开始创建一个 RESTful API(好吧,我已经尽力了,我正在尝试遵循这些模式)并且我偶然发现了一个我不确定如何处理的场景。我将解释当前的结构:

我的应用程序有 4 个控制器:

  • 客户
  • 付款
  • 日志

以客户控制器为例,我定义了以下动作:

  • GET /customers:返回客户列表
  • POST /customers:创建新客户
  • GET /customers/{id}:使用提供的 id 返回客户
  • PUT /customers/{id}:使用提供的 id 更新客户
  • DELETE /customers/{id}:销毁客户

这是客户控制器的完整代码:

namespace App\Http\Controllers;

use App\Customer;
use Illuminate\Http\Request;

class CustomerController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return Customer::all();
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $customer = Customer::create($request->all());
        return response()->json($customer, 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function show(Customer $customer)
    {
        return $customer;
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Customer $customer)
    {
        $customer->update($request->all());
        return response()->json($customer, 200);

    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Customer  $customer
     * @return \Illuminate\Http\Response
     */
    public function destroy(Customer $customer)
    {
        $customer->delete();
        return response()->json(null, 204);
    }
}

其他控制器中的代码非常相似。还需要注意的是:

  • 一个客户可以进行多次付款
  • 一个客户可以在日志中有多个记录

问题从这里开始:

我需要在前端显示一个包含所有客户数据(姓名、电子邮件、注册日期等)的摘要页面和一个显示付款次数的框和另一个显示日志中条目数的框。

我需要提出 3 个请求吗? (一个给 /customers/id,另一个给customers/id/payments,另一个给customers/id/logs)

如果我在 customers/id 调用中返回所有与客户相关的数据,我是否违反了 RESTful 约定?

【问题讨论】:

  • 我猜日志和付款是绑定在一起的?
  • 日志记录客户在系统中执行的所有操作以及执行这些操作的时间。例如,customer1 昨天登录。付款是客户付款的清单。他们需要付费才能使用该服务

标签: php laravel rest


【解决方案1】:

我正在使用 apigility,但我的回答仍然会与您的问题相关。根据 REST 术语(可以在此处找到 https://apigility.org/documentation/intro/first-rest-service#terminology),您正在谈论实体和集合。

/customers/id - entity,
/customers/id/payments - collection,
/customers/id/logs - collection. 

这是 3 个不同的请求。所以,是的,你需要提出 3 个不同的请求。

但是,老实说,如果您不需要对 paymentslogs 进行分页,则您只能向 /customers/id 发出一个请求,并且在响应中您可以拥有带有数组的字段

{
    "_links": {
        "self": {
            "href": "http://localhost:8080/status/3c10c391-f56c-4d04-a889-bd1bd8f746f0"
        }
    },
    "id": "3c10c391-f56c-4d04-a889-bd1bd8f746f0",
    ...
    _payments: [
        ...
    ],
    _logs: [
        ...
    ],
}

更新(与未来访问者的评论重复)。

另外,您应该注意 DTO。我想这个链接会很有趣https://stackoverflow.com/a/36175349/1581741

更新2

目前我会这样对待你的收藏/customers/id/payments

/payments?user_id=123

其中user_idpayments 表上的过滤字段。

【讨论】:

  • 非常感谢您的回答。这正是我的想法,在我的情况下 _payments 和 _logs 键只需要是一个数字。摘要页面只显示客户的摘要,系统还有其他屏幕可以查看完整的详细信息。只是为了确认一下,这种方法不会违反 REST 约定?我的意思是,我不仅要返回来自 Customer 模型的数据,还要创建一种混合模型
  • @TJistooshort,我不确定是否要打破 REST 约定。另外,您应该注意DTO。我想这个链接会很有趣stackoverflow.com/a/36175349/1581741
  • Laravel 提供了一个称为 API 资源 (laravel.com/docs/5.8/eloquent-resources) 的转换层。如果我说这是一个 DTO 实现,我说得对吗?
  • 如果您再次查看此链接apigility.org/documentation/intro/…,您将看到第三个术语“资源”。我想,laravel 资源是一样的。目前我没有使用 DTO,也没有完成对它的研究。等一下,我会更新我的答案。
  • 现在我将保留以前的url格式(customers/id/payments),因为付款列表也可以按状态(待处理、失败、成功)、日期等过滤.但是你的方法似乎也是正确的。有时,当我需要找出完成某事的最佳选择时,我会感到沮丧,但有很多选择可供选择
【解决方案2】:

我认为您的问题是您将 REST API 与数据库混淆了。它们不必遵循相同的结构。如果您需要 REST API,您可以轻松返回 GET /customers/{id} 的整个嵌套 JSON。

【讨论】:

    猜你喜欢
    • 2021-12-01
    • 2014-01-10
    • 2022-01-24
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多