在 Symfony 5 项目中,我们使用 APi 平台生成 REST API。
其中一个实体类称为
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
}
当我运行
php bin/console debug:router
时,它会显示此资源的以下路线:
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}
但是“元数据”这个词已经是复数了。不存在元数据这样的东西。如何关闭此端点的复数形式?
我尝试使用
shortName
:
* @ApiResource(
* shortName="FarmMetadata" // also "farm_metadata"
* )
但它不会改变输出。
如果我使用:
* @ApiResource(
* shortName="Metadata"
* )
然后更改路线名称和路径:
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}
但这不是我想要的。
我知道我可以为每个操作声明一条路径,但这会损害 DRY 原则。
我怎样才能达到预期的行为?
您可以在每个操作中使用“路径”选项。 参见 https://api-platform.com/docs/core/operations/#configuring-operations
例如
* shortName="Metadata",
* itemOperations={
* "get"={
* "path"="/metadata/{id}"
通过操作路径命名,您可以轻松地随心所欲。
将配置添加到
config/packages/api_platform.yaml
,将类和路径更改为您想要的名称和位置:
api_platform:
...
path_segment_name_generator: App\InfraStructure\ApiPlatform\Core\SingularPathSegmentNameGenerator
创建实现
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);
}
}
请参阅链接文档了解另一个示例,例如
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '-$1', $string));
我认为这不可能通过配置实现:这些路由是在私有方法
ApiPlatform\Core\Bridge\Symfony\Routing\ApiLoader::addRoute
中构建的(至少在我正在使用的 v2.6 中),并且这使用对复数器的静态调用 - 所以:装饰ApiLoader 不容易实现(因为 addRoute 方法是私有的),并且不可能交换生成路由的方式(由于使用静态方法调用)。
看起来您需要在他们的错误跟踪器中打开功能请求票...