【发布时间】:2023-03-05 22:21:02
【问题描述】:
也许我不明白这个想法,但我正在开始创建我的第一个使用 api 平台的测试应用程序。
我的搜索有自定义操作:
/**
* @Route(
* path="/api/pharmacies/search",
* name="pharmacy_search",
* defaults={
* "_api_resource_class"=Pharmacy::class,
* "_api_collection_operation_name"="search"
* }
* )
* @param Request $request
*
* @return Paginator
*/
public function search(Request $request)
{
$query = SearchQuery::createFromRequest($request);
return $this->pharmacyRepository->search($query);
}
以及存储库中的方法:
public function search(SearchQuery $searchQuery: Paginator
{
$firstResult = ($searchQuery->getPage() - 1) * self::ITEMS_PER_PAGE;
$qb = $this->createQueryBuilder('p')
/...
->setFirstResult($firstResult)
->setMaxResults(self::ITEMS_PER_PAGE);
$doctrinePaginator = new DoctrinePaginator($qb, false);
return new Paginator($doctrinePaginator);
}
它工作正常,但此操作不需要实体的所有字段以及与其他表的关系。目前,此操作会创建 22 个查询。我想在 DBAL/QueryBuilder 中创建查询并使用 DTO 返回分页对象。
public function search(SearchQuery $searchQuery)
{
.../
$qb = $this->createQueryBuilder('p')
->select('p.id')
->addSelect('p.name')/....
$rows = $qb->getQuery()->getArrayResult();
foreach ($rows as $row){
$data[] = new SearchPharmacy($row['id'], $row['name']);
}
return $data;
}
上面的代码可以工作,但如果响应不是 Pagination 对象,并且响应中没有 hydra:totalItems、hydra:next 等。
理论上我可以使用 DataTransformer 并将实体转换为 DTO,但这种方式不能简化数据库查询。
我能做到吗?
【问题讨论】:
-
DTO 模式和规范化器用于对 api 平台中的对象进行水合/脱水。您需要的是在您的基础对象上自定义过滤器,然后使用装饰器修改您的查询。通过这种方式,您允许 api-platform 使用所有现有功能而不会引入复杂性
-
自定义控制器和 DTO 或规范器的角色需要手动水合实体对象。当您不使用学说作为您的 dbal 并且具有自定义数据库接口时,它很有用。 Api 平台非常复杂,有多种方法可以做同样的事情,您需要选择正确的方法来完成高效的任务。自定义过滤器在应用时只会覆盖查询。
标签: php api symfony doctrine api-platform.com