首页 > 解决方案 > Laravel JSON API:如何从数据库创建自定义虚拟资源(用于聚合值)?

问题描述

从那以后,我试图弄清楚如何将“虚拟”资源添加到我的 Laravel JSON API ( "cloudcreativity/laravel-json-api": "~2.0")。解释:

假设我在数据库表和 Eloquent 模型中有时间记录,JSON API 包使用该模型将其自动转换为资源,显示在/api/v1/timerecords. 开箱即用,只需添加一个适配器、一个模式和一些微小的配置!时间记录示例:

id | customer_id | user_id | ts_start | ts_end | hours | amount_xy | ...
1  | 123         | 5       | 2020-0...| 2020...| 4.5   | 95.2      | ...
2  | 987         | 5       | 2020-0...| 2020...| 2.75  | 32.8      | ...

但是现在我想拥有一个/api/v1/timeaggregates带有计算值的 API 端点,例如COUNT(id) AS num_records, SUM(hours) AS sum_hours, AVG(amount_xy) AS avg_xy,这些记录可以通过各种参数聚合(或过滤器以保持 API 术语?!),例如:

当然,这个资源必须是只读的(GET),因为它是“虚拟的”。但我什至无法接近任何工作。搜索整个网络也一无所获,这让我更加好奇,因为我发现这样的功能对于 API 来说是一项非常常见的任务,不是吗?!到目前为止我已经尝试过:

也许我在这里遗漏了一些巨大的东西,或者问题可能是使用了不支持这些东西的 CloudCreativity 包(这再次让我想知道,因为该包似乎非常专业,有很好的文档)。

如果你们中的任何人可以给我一个提示,我会appreachiate。提前谢谢!

标签: laraveleloquentjson-api

解决方案


我创建了一个有点丑陋的解决方法。如果有更干净的解决方案,请随时赐教^^

首先,我创建了一个“虚拟”模型,它不是真正的虚拟,因为我使用现有的“时间记录”表:

class Timeaggregate extends Model {
    protected $table = 'timerecords';
}

在资源适配器中,我重写了queryAll()计算聚合值的方法:

    protected function queryAll($query, EncodingParametersInterface $parameters) {
        $this->with($query, $parameters);
        $this->applyFilters($query, collect($parameters->getFilteringParameters()));

        $query->selectRaw('COUNT(id) as count_records')
            ->selectRaw('SUM(hours) AS sum_hours');

        return $query->first();
    }

比在资源模式 getAttributes() 方法中,我可以简单地使用例如将计算字段添加到响应中$resource->sum_hours

另一种解决方案可能是创建一个非 eloquent 资源并手动执行数据库查询以填充所需的属性。但我还没有测试过,因为我发现我的需求与真实的现有资源密切相关,所以在我看来它仍然应该是一个 Eloquent 资源。


推荐阅读