在使用API平台中的外部API源(条带)时尝试过滤结果时,我遇到了问题。
我需要做的是返回指定客户的订阅列表。因此,转到http://localhost/api/subscriptions?customer=123foo将返回与此客户匹配的所有记录。
现在,由于ORM \ Filter,下面的代码将引发错误,并且没有它就可以正常工作,因为实际的过滤是在Stripes API上执行的,而不是我本人,但是,我真的希望Swagger-API GUI能够执行有过滤盒。
简而言之,当使用外部数据源时,如何在Entity中显示注释,以便在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 /过滤器:
在null上调用成员函数getClassMetadata()
任何指针将不胜感激。
答案 0 :(得分: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;
}
}