【问题标题】:Create an endpoint for report with API Platform (https://api-platform.com)使用 API 平台 (https://api-platform.com) 为报告创建端点
【发布时间】:2020-12-06 01:19:36
【问题描述】:

举个例子:

我想用 API 平台实现一个学生报告端点。

api/报告/学生

我有以下表格:

学生

id,
name,
address


发票

id,
description,
amount,
status,
student_id

我想使用 API 端点返回以下信息:

{
    data: [
       student_id: 1,
       student_name: john,
       outstanding_amount: 200 (Total of unpaid bill)
    ],
    [
       student_id: 2,
       student_name: mike,
       outstanding_amount: 300 (Total of unpaid bill)
    ]

}

只是想知道使用 API 平台 (https://api-platform.com) 为报告编写 API 端点的最佳做法是什么。

报表端点需要排序、连接表格和分页等。

使用 API 平台实现这一目标的最佳做法是什么?这是我们可以通过 GraphQL 实现的,还是我们需要将它与控制器操作绑定才能做到这一点?

谢谢。

【问题讨论】:

  • 我认为没有任何官方的最佳实践,这可能会导致没有答案或多个基于意见的答案。请改为开始处理您的任务,并在遇到问题时提出具体问题。对您的问题的简短回答是:既可以使用 GraphQL 也可以使用 REST API,并且有多种方法可以控制您的实体的序列化方式。哪种解决方案是“最好的”完全取决于您的标准,不能一概而论。
  • 有关官方最佳实践,请参阅 General Design Considerations,您的 DataProvider 的示例为 here。但是,如果您想重用现有的过滤器,请参阅我的 tutorial 的第 9 章以获取替代方案。它使用 REST,但如果您将此类操作和操作名称添加到 \App\DataProvider\DayTotalsPerEmployeeCollectionDataProvider::supports,它应该可以与 GraphQL 一起使用。

标签: php symfony api-platform.com


【解决方案1】:

事实上,假设您安装了核心,您就拥有 API 平台所需的一切。

排序

对于排序,如果您查看Filters 部分,您可以使用名为Order Filter 的过滤器,它基本上是一个排序 过滤器。

===========

分页

您在使用Pagination 时可以使用许多功能。您可以控制每页的项目数,也可以启用/禁用特定资源的分页。

===========

加入表格

据我了解,您需要通过执行 JOIN 从数据库中为您的端点获取一些自定义结果集。创建Custom doctrine filters 应该可以帮助您实现这一目标。

===========

此外,为了获得更大的灵活性,可以使用Custom controller action。 正如 dbrumann 所说,我认为也没有任何官方的最佳实践。您只需使用可用的功能。当然你也可以使用 GraphQL,但老实说我从来没有使用过它。在我看来,它似乎是一个强大的工具。这取决于你。

【讨论】:

    【解决方案2】:

    可能可行的最简单的解决方案:

    namespace App\Entity;
    
    use ApiPlatform\Core\Annotation\ApiResource;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Serializer\Annotation\Groups;
    use ApiPlatform\Core\Annotation\ApiFilter;
    use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    
    /**
     * @ApiResource(
     *     normalizationContext={"groups"={"student:read"}},
     *     attributes={"order"={"name", "address"}},
     *     itemOperations={
     *          "get",
     *          "put",
     *          "delete"
     *     },
     *     collectionOperations={
     *         "get",
     *          "post",
     *          "get_report"={
     *             "method"="GET",
     *             "path"="/students/report",
     *             "normalization_context"={"groups"={"student:report"}}
     *          }
     *     }
     * )
     * @ApiFilter(OrderFilter::class)
     * @ORM\Entity
     */
    class Student
    {
        /**
         * @var int
         * @ORM\Id
         * @ORM\GeneratedValue
         * @ORM\Column(type="integer")
         * @Groups({"student:report"})
         */
        public $id;
    
        /**
         * @var string
         * @ORM\Column
         * @Assert\NotBlank
         * @Assert\Length(max=255)
         * @Groups({"student:read", "student:report"})
         */
        public $name;
    
        /**
         * @var string|null
         * @ORM\Column(nullable=true)
         * @Assert\Length(max=255)
         * @Groups({"student:read"})
         */
        public $address;
    
        /**
         * @var Collection
         * @ORM\OneToMany(targetEntity="App\Entity\Invoice", mappedBy="student")
         * @Groups({"student:read"})
         */
        public $invoices;
    
        public function __construct()
        {
            $this->invoices = new ArrayCollection();
        }
    
        /**
         * @return int|float
         * @Groups({"student:report"})
         */
        public function getOutstandingAmount()
        {
            $result = 0;
            foreach ($this->invoices as $invoice) {
                if ($invoice->getStatus() == Invoice::STATUS_OUTSTANDING) {
                    $result += $invoice->getAmount();
                }
            }
            return $result;
        }
    }
    

    输出中的属性名称不会以 student_ 为前缀,如果需要,请尝试 DTO's

    当然最好有私有属性和 getter 和 setter,但这不是最简单的解决方案 ;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 2021-08-20
      • 1970-01-01
      相关资源
      最近更新 更多