无实体操作 [英] Operation without entity

查看:27
本文介绍了无实体操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找解决方案,但我找到的解决方案都没有真正让我做我想做的.我只想创建不一定需要使用实体或 id 的路由.你能帮我文档不清楚这样做吗.

I've been looking for a solution for a while but none of the one I find really allows me to do what I want. I would just like to create routes that don't necessarily require an entity or id to be used. Can you help me the documentation is not clear to do this.

先谢谢你.

推荐答案

正如您在 一般设计注意事项,只需制作一个普通的 PHP 类 (POPO).给它一个像这样的 ApiResource 注释:

As you can read in the General Design Considerations, just make an ordinary PHP class (POPO). Give it an ApiResource annontation like this:

 * @ApiResource(
 *     collectionOperations={
 *         "post"
 *     },
 *     itemOperations={}
 * )

确保您的类所在的文件夹位于 api/config/packages/api_platform.yaml 的路径列表中.通常有以下配置:

Make sure the folder your class is in is in the paths list in api/config/packages/api_platform.yaml. There usually is the following configuration:

api_platform:
    mapping:
        paths: ['%kernel.project_dir%/src/Entity']

如果您的类不在实体文件夹中,您应该添加您的路径.

You should add your path if your class is not in the Entity folder.

Api 平台将期望 json 被发布并尝试将其反序列化为您的类的实例.制作自定义 DataPersister 来处理实例,例如,如果您的类是应用\ApiCommand\Doit:

Api Platform will expect json to be posted and try to unserialize it into an instance of your class. Make a custom DataPersister to process the instance, for example if your class is App\ApiCommand\Doit:

namespace App\DataPersister;

use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\ApiCommand\Doit;
use App\ApiResult\DoitResult;

final class DoitDataPersister implements ContextAwareDataPersisterInterface
{
    public function supports($data, array $context = []): bool
    {
        return $data instanceof Doit;
    }

    public function persist($data, array $context = [])
    {
        // code to process $data

        $result = new DoitResult();
        $result->description = 'Hello world';
        return $result;
    }

    public function remove($data, array $context = [])
    {
      // will not be called if you have no delete operation
    }
}

如果您需要 Doctrine,请添加:

If you need Doctrine, add:

    public function __construct(ManagerRegistry $managerRegistry)
    {
        $this->managerRegistry = $managerRegistry;
    }

参见注入扩展 了解如何使用它.

See Injecting Extensions for how to use it.

注意 ::persist 返回的结果不是 Doit 的实例.如果您返回 Doit api 平台将尝试将其序列化为您的操作结果.但是我们已经将Doit标记为ApiResource,因此(?)api平台寻找可以检索它的项目操作,导致错误没有与类型App\ApiCommand\Doit相关的项目路由".为了避免这种情况,您可以返回 Symfony 序列化程序可以序列化的任何不是 ApiResource 的对象.在示例中是 DoitResult 的一个实例.或者你可以返回一个 Symfony\Component\HttpFoundation\Response 的实例,但是你必须自己处理序列化.

Notice that the result returned by ::persist is not an instance of Doit. If you return a Doit api platform will try to serialize that as the result of your operation. But we have marked Doit as an ApiResource so (?) api platform looks for an item operation that can retrieve it, resulting in an error "No item route associated with the type App\ApiCommand\Doit". To avoid this you can return any object that Symfonies serializer can serialize that is not an ApiResource. In the example an instance of DoitResult. Alternatively you can return an instance of Symfony\Component\HttpFoundation\Response but then you have to take care of the serialization yourself.

post 操作应该已经可以工作了,但是 swagger 文档是由元数据制作的.要告诉 api 平台它应该期望返回 DoitResult,请更改 @ApiResource 注释:

The post operation should already work, but the swagger docs are made from metadata. To tell api platform that it should expect a DoitResult to be returned, change the @ApiResource annotation:

 *     collectionOperations={
 *         "post"={
 *             "output"=DoitResult::class
 *         }
 *     },

这将在 swagger 文档中为 DoitResult 添加一个新类型,但描述仍然是错误的.您可以使用 SwaggerDecorator 更正它们.这是 201 帖子回复的一个:

This will the add a new type for DoitResult to the swagger docs, but the descriptions are still wrong. You can correct them using a SwaggerDecorator. Here is one for a 201 post response:

namespace App\Swagger;

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

final class SwaggerDecorator implements NormalizerInterface
{
    private $decorated;

    public function __construct(NormalizerInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function normalize($object, string $format = null, array $context = [])
    {
        $summary = 'short explanation about DoitResult';
        $docs = $this->decorated->normalize($object, $format, $context);
        $docs['paths']['/doit']['post']['responses']['201']['description'] = 'Additional explanation about DoitResult';

        $responseContent = $docs['paths']['/doit']['post']['responses']['201']['content'];
        $this->setByRef($docs, $responseContent['application/ld+json']['schema']['properties']['hydra:member']['items']['$ref'],
            'description', $summary);
        $this->setByRef($docs, $responseContent['application/json']['schema']['items']['$ref'],
            'description', $summary);

        return $docs;
    }

    public function supportsNormalization($data, string $format = null)
    {
        return $this->decorated->supportsNormalization($data, $format);
    }

    private function setByRef(&$docs, $ref, $key, $value)
    {
        $pieces = explode('/', substr($ref, 2));
        $sub =& $docs;
        foreach ($pieces as $piece) {
            $sub =& $sub[$piece];
        }
        $sub[$key] = $value;
    }
}

要配置服务,请将以下内容添加到 api/config/services.yaml:

To configure the service add the following to api/config/services.yaml:

'App\Swagger\SwaggerDecorator':
    decorates: 'api_platform.swagger.normalizer.api_gateway'
    arguments: [ '@App\Swagger\SwaggerDecorator.inner' ]
    autoconfigure: false

如果您的发布操作实际上并未创建某些内容,您可能不喜欢 201 响应.您可以通过在@ApiResource 注释中指定响应代码来更改它,例如:

If your post operation is not actually creating something you may not like the 201 response. You can change that by specifying the response code in the @ApiResource annotation, for example:

 *     collectionOperations={
 *         "post"={
 *             "output"=DoitResult::class,
 *             "status"=200
 *         }
 *     },

您可能需要相应地调整 SwaggerDecorator.

You may want to adapt the SwaggerDecorator accordingly.

创建一个get"收集操作类似,但你需要制作一个 DataProvider 而不是一个数据保持器.我的 教程 的 Chapter9-api 分支包含一个 SwaggerDecorator 的示例,用于集合响应.

Creating a "get" collection operation is similar, but you need to make a DataProvider instead of a DataPersister. The chapter9-api branch of my tutorial contains an example of a SwaggerDecorator for a collection response.

这篇关于无实体操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆