2

I'm trying to write custom GET endpoints, which must have one or more custom parameters, but not built on top of specific entity.

Something like: /assets/{device_id}/{scene_id}/{maybe_other_param}

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...

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.

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?

1
  • 1
    Doing so doesn't show anything in swaggerui. Also I don't even know how to define my parameters and how to get them in this controller. It's just not written anywhere in documentation nor in google, at least I can't find anything, any example for the last three days. Commented Jun 14, 2019 at 8:52

1 Answer 1

3

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];
    }
}

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.