Api平台:使用PUT创建资源 [英] Api-Platform: using PUT for creating resources

查看:75
本文介绍了Api平台:使用PUT创建资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用PUT方法创建资源.它们由UUID标识,并且由于可以在客户端上创建UUID,所以我希望启用以下行为:

I would like to use the PUT method for creating resources. They are identified by an UUID, and since it is possible to create UUIDs on the client side, I would like to enable the following behaviour:

  • 在PUT上/api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881如果存在此资源,请对其进行更新
  • 在PUT/api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881上创建此资源

可以通过实现 ItemDataProviderInterface / RestrictedDataProviderInterface 来实现.

It's possible to achieve this by implementing an ItemDataProviderInterface / RestrictedDataProviderInterface.

但是,我的资源实际上是子资源,所以假设我要创建一个引用现有 Author 的新 Book .

However, my resource is actually a subresource, so let's say I want to create a new Book which references an existing Author.

我的构造函数如下:

/**
 * Book constructor
 */
public function __construct(Author $author, string $uuid) {
    $this->author = $author;
    $this->id = $uuid;
}

但是我不知道如何从我的 BookItemProvider 中访问 Author 实体(在请求正文中提供).

But I don't know how to access the Author entity (provided in the request body) from my BookItemProvider.

有什么想法吗?

推荐答案

在API平台中,创建项目时应该发生的许多事情基于请求的类型.更改会很复杂.

In API Platform many things that should occur on item creation is based on the kind of request it is. It would be complicated to change.

有两种方法可以满足您的需求.

Here are 2 possibilities to make what you want.

首先,您可以考虑执行自定义路由并使用自己的逻辑.如果这样做,您可能会很高兴知道,在自定义路由上使用选项 _api_resource_class 将启用APIPlaform的某些侦听器,并且省去了一些工作.

First, you may consider to do a custom route and use your own logic. If you do it you will probably be happy to know that using the option _api_resource_class on your custom route will enable some listeners of APIPlaform and avoid you some work.

第二种解决方案,例如,如果需要全局行为,则是覆盖API平台.您的主要问题是ApiPlatform的 ReadListener ,如果找不到您的资源,它将抛出异常.这段代码可能不起作用,但是这里是如何覆盖此行为的想法:

The second solution, if you need global behavior for example, is to override API Platform. Your main problem for this is the ReadListener of ApiPlatform that will throw an exception if it can't found your resource. This code may not work but here is the idea of how to override this behavior:

class CustomReadListener
{
    private $decoratedListener;

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

    public function onKernelRequest(GetResponseEvent $event)
    {
        try {
            $this->decoratedListener->onKernelRequest($event);
        } catch (NotFoundHttpException $e) {
            // Don't forget to throw the exception if the http method isn't PUT 
            // else you're gonna break the 404 errors
            $request = $event->getRequest();

            if (Request::METHOD_PUT !== $request->getMethod()) {
                throw $e;
            }

            // 2 solutions here:

            // 1st is doing nothing except add the id inside request data
            // so the deserializer listener will be able to build your object


            // 2nd is to build the object, here is a possible implementation

            // The resource class is stored in this property
            $resourceClass = $request->attributes->get('_api_resource_class');

            // You may want to use a factory? Do your magic.
            $request->attributes->set('data', new $resourceClass());
        }
    }
}

并且您需要指定配置以将您的类声明为服务装饰器:

And you need to specify a configuration to declare your class as service decorator:

services:
    CustomReadListener:
        decorate: api_platform.listener.request.read
        arguments:
            - "@CustomReadListener.inner"

希望它会有所帮助.:)

Hope it helps. :)

更多信息:

这篇关于Api平台:使用PUT创建资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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