问题描述
我正在尝试编写自定义 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?
推荐答案
如果您希望将路径中的参数直接传递给您的控制器,您需要将操作配置为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();
}
}
我使用以下控制器类对其进行了测试:
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 或其他不是资源的 DTO,并将 output= 配置为输出的类.然后,您也需要为此更正 swagger 文档,请参阅我的 教程的 Chapter9-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.
这篇关于如何使用与任何特定实体无关的参数编写自定义端点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!