如何使用不与任何特定实体相关的参数编写自定义端点 [英] How to write custom endpoints with parameters not related to any specific entity
问题描述
我正在尝试编写自定义GET端点,该端点必须具有一个或多个自定义参数,但不能建立在特定实体之上.
I'm trying to write custom GET endpoints, which must have one or more custom parameters, but not built on top of specific entity.
类似:/assets/{device_id}/{scene_id}/{maybe_other_param}
Something like: /assets/{device_id}/{scene_id}/{maybe_other_param}
我想这只是自己的控制器类,我在其中进行一些操作,从输入中计算值,手动读取一些数据并返回实体数组.我唯一得到的是一个Asset实体,但是它需要{device}和{scene}才能成为该实体的属性...
which I imagine to be just own controller class, in which I do something, calculate values from input, read some data manually and return array of entities. What I only get is an Asset entity, but it requires {device} and {scene} to be properties of this entity...
我不希望它通过其属性作为带有过滤器的暴露实体来工作,我只需要在API中看到简单的终结点,就象需要一些参数,处理和返回json的普通自定义控制器一样.
I don't want this to work as exposed entity with filter by its properties, I just need simple endpoint seen in API, as normal custom controller which takes some params, do stuff and return json.
这听起来很简单,但是我阅读了大量的文档和示例,但仍然一无所获.在API平台上甚至可以做到这一点吗?
It sounds like simple thing, but I read tons of documentation and examples and still didn't find anything. Is this even possible in API-platform?
推荐答案
如果要将路径中的参数直接传递到Controller,则需要使用"read" = false配置操作.这是我可以通过这种收集操作使用的最简单的资产资源:
If you want the parameters from the path to be passed to your Controller directly you need to configure the operation with "read"=false. Here is the simpelest Asset resource i could make to work with such a collection operation:
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use App\Controller\GetAssetCollectionByPathParams;
/**
* @ApiResource(
* collectionOperations={
* "get",
* "get_by_path_params"={
* "method"="GET",
* "controller"=GetAssetCollectionByPathParams::class,
* "path"="/assets/{device_id}/{scene_id}/{maybe_other_param?}",
* "read"=false,
* "pagination_enabled"=false,
* "openapi_context"={
* "summary"="Get by path parameters",
* "parameters"={
* {
* "name" = "device_id",
* "in" = "path",
* "required" = true,
* "type" = "integer"
* },
* {
* "name" = "scene_id",
* "in" = "path",
* "required" = true,
* "type" = "string"
* },
* {
* "name" = "maybe_other_param",
* "in" = "path",
* "required" = false,
* "type" = "string"
* }
* }
* }
* }
* },
* itemOperations={
* "get"
* }
* )
*/
class Asset
{
/** @var string */
public $description;
/**
* @return int
* @ApiProperty(identifier=true)
*/
public function getId()
{
return time();
}
}
我使用以下Contoller类对其进行了测试:
I tested it with the following Contoller class:
namespace App\Controller;
use App\Entity\Asset;
class GetAssetCollectionByPathParams
{
/**
* @return Asset[]
*/
public function __invoke($device_id, $scene_id, $maybe_other_param=null) :array
{
$result = new Asset();
$result->description = "GetAssetCollectionByPathParams result for device_id: $device_id, scene_id: $scene_id, maybe_other_param: $maybe_other_param";
return [$result];
}
}
也适用于GET项目操作.对于其输出是资源的收集操作,不要删除任何默认的"get"操作.否则IriConverter的操作将无法生成必要的iri.如果您不希望必须输出DTO或它不是资源,则将output =配置为输出的类.然后,您也需要对此进行修改,请参阅我的教程的第9-api分支以一个集合操作符为例.对于POST操作,请参见此问题的答案.
Also works for GET item operations. With collection operations whose output is a resource don't remove any of the default "get" operations from otherwise the IriConverter can not produce the necessary iri's. If you don't want that you must output a DTO or so that is not a resource and configure output= to the class of the output. Then you need to correct the swagger docs for that too, see chapter9-api branch of my tutorial for an example with a collection operaton. For a POST operation see my answer to this question.
这篇关于如何使用不与任何特定实体相关的参数编写自定义端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!