You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在API Platform中让Question仅嵌入5条最新Answer(GET操作)

API Platform 实现问题关联答案的两种获取方式

问题背景

现有 Question 和 Answer 两个实体,ORM 关联关系如下:

Question 实体代码

#[ApiResource]
class Question
{
   //...
   
   #[ORM\OneToMany(mappedBy: "question", targetEntity: Answer::class)]
   private Collection $answers;
}

Answer 实体代码

#[ApiResource]
class Answer
{
   //...
   
   #[ORM\ManyToOne(inversedBy: 'answers')]
   #[ORM\JoinColumn(nullable: false)]
   private Question $question;
}

需求:

  • 获取 Question 详情时,仅嵌入5条最新的Answer
  • 同时提供独立端点,支持分页获取某 Question 的所有 Answer

解决方案

1. 为 Question 添加「最新5条答案」的嵌入字段

直接修改原有 $answers 字段会干扰全量查询,建议新增专门字段(如 latestAnswers)承载需求:

#[ApiResource]
class Question
{
   // 原有关联,保留用于全量查询
   #[ORM\OneToMany(mappedBy: "question", targetEntity: Answer::class)]
   private Collection $answers;

   // 新增字段:返回最新5条答案,嵌入到Question详情
   #[ApiProperty(readableLink: false)]
   public function getLatestAnswers(): Collection
   {
       // 按创建时间倒序排序后取前5条
       return $this->answers->sort(function (Answer $a, Answer $b) {
           return $b->getCreatedAt() <=> $a->getCreatedAt();
       })->slice(0, 5);
   }
}

注意:需确保 Answer 实体包含 createdAt(或类似时间戳字段)及对应的 getter 方法,若没有需先添加ORM映射。

2. 配置 Answer 端点,支持按 Question 过滤+分页

在 Answer 的 ApiResource 注解中开启分页和字段过滤:

use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;

#[ApiResource(
    operations: [
        new GetCollection(
            paginationEnabled: true,
            paginationItemsPerPage: 10 // 默认每页10条,可通过URL参数覆盖
        )
    ]
)]
#[ApiFilter(SearchFilter::class, properties: ['question' => 'exact'])]
class Answer
{
   //...
   
   #[ORM\ManyToOne(inversedBy: 'answers')]
   #[ORM\JoinColumn(nullable: false)]
   private Question $question;

   #[ORM\Column(type: 'datetime_immutable')]
   private \DateTimeImmutable $createdAt;

   public function getCreatedAt(): \DateTimeImmutable
   {
       return $this->createdAt;
   }
}

3. 验证效果

  • 获取 Question 详情时,响应会包含 latestAnswers 字段,返回5条最新答案
  • 调用 GET /answers?question=<QuestionID> 即可分页获取该问题的所有答案,可通过 page 和 itemsPerPage 参数自定义分页规则

性能优化(可选)

若答案数量庞大,内存排序会有性能损耗,可改用ORM自定义查询实现:

步骤1:修改 Question 实体关联

#[ApiResource]
class Question
{
   //...
   
   #[ORM\OneToMany(mappedBy: "question", targetEntity: Answer::class)]
   private Collection $answers;

   #[ORM\OneToMany(mappedBy: "question", targetEntity: Answer::class)]
   #[ORM\OrderBy(['createdAt' => 'DESC'])]
   #[ApiProperty(readableLink: false)]
   private Collection $latestAnswers;

   public function __construct()
   {
       $this->answers = new ArrayCollection();
       $this->latestAnswers = new ArrayCollection();
   }
}

步骤2:配置 Question 详情使用自定义Repository

use ApiPlatform\Metadata\Get;
use App\Repository\QuestionRepository;

#[ApiResource(
    operations: [
        new Get(
            provider: [QuestionRepository::class, 'findOneByIdWithLatestAnswers']
        )
    ]
)]
class Question
{
   //...
}

步骤3:实现 Repository 查询方法

class QuestionRepository extends ServiceEntityRepository
{
   //...

   public function findOneByIdWithLatestAnswers(int $id): ?Question
   {
       return $this->createQueryBuilder('q')
           ->leftJoin('q.latestAnswers', 'a')
           ->where('q.id = :id')
           ->setParameter('id', $id)
           ->setMaxResults(5)
           ->getQuery()
           ->getOneOrNullResult();
   }
}

内容的提问来源于stack exchange,提问作者Osmanys Fuentes-Lombá

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:15:41