【问题标题】:API-Platform: Filtering Custom Data ProviderAPI 平台:过滤自定义数据提供者
【发布时间】:2018-09-25 10:41:08
【问题描述】:

当我在 API-Platform 中使用外部 API 源 (Stripe) 时尝试过滤我的结果时遇到问题。

我需要做的是返回指定客户的订阅列表。所以转到http://localhost/api/subscriptions?customer=123foo 将返回与该客户匹配的所有记录。

现在,由于 ORM\Filter 的原因,下面的代码会引发错误,没有它也可以正常工作,因为实际过滤是在 Stripes API 上执行的,而不是由我执行的,但是,我真的希望 Swagger-API GUI 能够有过滤盒。

简而言之,当使用外部数据源时,如何让我的实体中的注释显示在 Swagger UI 中的可搜索字段。

我所拥有的是一个实体,如下所示(出于示例目的而简化):

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use Symfony\Component\Serializer\Annotation\Groups;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Annotation\ApiFilter;

/**
 * Subscriptions allow you to charge a customer on a recurring basis. A subscription ties a customer to a particular plan you've created.
 * @ApiResource()
 * @ApiFilter(SearchFilter::class, properties={"customer": "exact"})
 * @package App\Entity
 */
class Subscription
{
     /**
     * Unique identifier for the object.
     * @ApiProperty(identifier=true)
     * @var string | null
     */
    protected $id; 

    /**
     * ID of the customer who owns the subscription.
     * @var string | null
     */
    protected $customer;

    // Plus a bunch more properties and their Getters & Setters
}

还有 SubscriptionCollectionDataProvider:

<?php

namespace App\DataProvider;

use App\Entity\Subscription;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Controller\BaseController;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Class SubscriptionCollectionDataProvider
 * @package App\DataProvider
 * @author dhayward
 */
final class SubscriptionCollectionDataProvider extends BaseController implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{

    protected $requestStack;

    /**
     * SubscriptionCollectionDataProvider constructor.
     * @param RequestStack $requestStack
     */
    public function __construct(RequestStack $requestStack)
    {
        $this->request = $requestStack->getCurrentRequest();
    }

    /**
     * @param string $resourceClass
     * @param string|null $operationName
     * @param array $context
     * @return bool
     */
    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
    {
        return Subscription::class === $resourceClass;
    }

    /**
     * @param string $resourceClass
     * @param string|null $operationName
     * @return \Generator
     * @throws \Stripe\Error\Api
     */
    public function getCollection(string $resourceClass, string $operationName = null): \Generator
    {
        $customer = $this->request->get("customer");

        $data = \Stripe\Subscription::all(["customer" => $customer]);

        foreach($data['data'] as $subscriptionObject){
            $this->serializer()->deserialize(json_encode($subscriptionObject), Subscription::class, 'json', array('object_to_populate' => $subscription = new Subscription()));
            yield $subscription;
        }
    }

}

错误结果,大概是因为我使用了没有任何 ORM 设置的 ORM/Filter:

在 null 上调用成员函数 getClassMetadata()

任何指针将不胜感激。

【问题讨论】:

    标签: php symfony swagger api-platform.com


    【解决方案1】:

    所以我终于设法解决了。就像创建我自己的SearchFilter 版本一样简单,实现ApiPlatform\Core\Api\FilterInterface

    <?php
    
    namespace App\Filter;
    
    use ApiPlatform\Core\Api\FilterInterface;
    
    /**
     * Class SearchFilter
     * @package App\Filter
     */
    class SearchFilter implements FilterInterface
    {
        /**
         * @var string Exact matching
         */
        const STRATEGY_EXACT = 'exact';
    
        /**
         * @var string The value must be contained in the field
         */
        const STRATEGY_PARTIAL = 'partial';
    
        /**
         * @var string Finds fields that are starting with the value
         */
        const STRATEGY_START = 'start';
    
        /**
         * @var string Finds fields that are ending with the value
         */
        const STRATEGY_END = 'end';
    
        /**
         * @var string Finds fields that are starting with the word
         */
        const STRATEGY_WORD_START = 'word_start';
    
        protected $properties;
    
        /**
         * SearchFilter constructor.
         * @param array|null $properties
         */
        public function __construct(array $properties = null)
        {
            $this->properties = $properties;
        }
    
        /**
         * {@inheritdoc}
         */
        public function getDescription(string $resourceClass): array
        {
            $description = [];
    
            $properties = $this->properties;
    
            foreach ($properties as $property => $strategy) {
    
                    $filterParameterNames = [
                        $property,
                        $property.'[]',
                    ];
    
                    foreach ($filterParameterNames as $filterParameterName) {
                        $description[$filterParameterName] = [
                            'property' => $property,
                            'type' => 'string',
                            'required' => false,
                            'strategy' => self::STRATEGY_EXACT,
                            'is_collection' => '[]' === substr($filterParameterName, -2),
                        ];
                    }
                }
    
            return $description;
        }
    
    }
    

    【讨论】:

    • 也可以通过openapi_context添加过滤器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2022-11-04
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    相关资源
    最近更新 更多