cezar
cezar

Reputation: 12012

Turn off pluralisation for an endpoint in APi Platform

In a Symfony 5 project we're using the APi Platform to generate a REST API.

One of the entity classes is called FarmMetadata.

<?php

namespace App\Entity;

use  ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ApiResource()
 * @ORM\Table(... some settings ...)
 * @ORM\Entity
 */
class FarmMetadata
{
    // properties and methods
}

When I run php bin/console debug:router it shows the following routes for this resource:

api_farm_metadatas_get_collection    GET      ANY      ANY    /api/farm_metadatas.{_format}        
api_farm_metadatas_post_collection   POST     ANY      ANY    /api/farm_metadatas.{_format}        
api_farm_metadatas_get_item          GET      ANY      ANY    /api/farm_metadatas/{id}.{_format}   
api_farm_metadatas_delete_item       DELETE   ANY      ANY    /api/farm_metadatas/{id}.{_format}   
api_farm_metadatas_put_item          PUT      ANY      ANY    /api/farm_metadatas/{id}.{_format}   
api_farm_metadatas_patch_item        PATCH    ANY      ANY    /api/farm_metadatas/{id}.{_format}

However the word "metadata" is already plural. There's no such thing as metadatas. How can I turn off the pluralisation for this endpoint?

I tried using shortName:

* @ApiResource(
*     shortName="FarmMetadata" // also "farm_metadata"
* )

but it doesn't change the output.

If I use:

* @ApiResource(
*     shortName="Metadata"
* )

then the route names and paths are changed:

api_metadata_get_collection         GET      ANY      ANY    /api/metadata.{_format}              
api_metadata_post_collection        POST     ANY      ANY    /api/metadata.{_format}              
api_metadata_get_item               GET      ANY      ANY    /api/metadata/{id}.{_format}         
api_metadata_delete_item            DELETE   ANY      ANY    /api/metadata/{id}.{_format}         
api_metadata_put_item               PUT      ANY      ANY    /api/metadata/{id}.{_format}         
api_metadata_patch_item             PATCH    ANY      ANY    /api/metadata/{id}.{_format}

but that's not what I want.

I know that I can declare a path for every operation, but that would hurt the DRY principle.

How can I achieve the desired behaviour?

Upvotes: 2

Views: 1601

Answers (3)

MGDSoftware
MGDSoftware

Reputation: 157

You can do easily as you want with the Operation Path Naming.

Add the config to config/packages/api_platform.yaml, changing the class and path to your desired name and location:

api_platform:
    ...
    path_segment_name_generator: App\InfraStructure\ApiPlatform\Core\SingularPathSegmentNameGenerator

Create the necessary class which implements PathSegmentNameGeneratorInterface:

<?php

declare(strict_types=1);

namespace App\InfraStructure\ApiPlatform\Core;

use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface;
use ApiPlatform\Core\Util\Inflector;

final class SingularPathSegmentNameGenerator implements PathSegmentNameGeneratorInterface
{
    public function getSegmentName(string $name, bool $collection = true): string
    {
        return Inflector::tableize($name);
    }
}

See the linked documentation for another example, e.g.
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '-$1', $string));

Upvotes: 2

mundoludo
mundoludo

Reputation: 41

You could use "path" option on each operation. Cf https://api-platform.com/docs/core/operations/#configuring-operations

For example

 *     shortName="Metadata",
 *     itemOperations={
 *         "get"={
 *              "path"="/metadata/{id}"

Upvotes: 4

Nico Haase
Nico Haase

Reputation: 12095

I don't think this is possible by configuration: these routes are built in the private method ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::addRoute (at least in v2.6 which I'm using), and this uses a static call to a pluralizer - so: decorating the ApiLoader is not easily possible (as the addRoute method is private), and exchanging the ways of generating the route is not possible (due to the usage of a static method call).

Looks like you need to open a feature request ticket in their bug tracker...

Upvotes: 1

Related Questions