В настоящее время у меня возникают проблемы при попытке отфильтровать мои результаты при использовании внешнего источника API (Stripe) в API-Platform.
Что мне нужно сделать, так это вернуть список подписок для указанного клиента. Таким образом, переход к http: // локальный хост / api / подписки? customer = 123foo вернет все записи, соответствующие этому клиенту.
Теперь приведенный ниже код выдает ошибку из-за ORM \ Filter и будет работать без него, поскольку фактическая фильтрация выполняется в Stripes API, а не мной, НО, я действительно хочу, чтобы графический интерфейс Swagger-API имел фильтр коробка.
Короче говоря, как мне заставить аннотации в моей сущности отображать доступные для поиска поля в пользовательском интерфейсе Swagger при использовании внешнего источника данных.
У меня есть сущность, как показано ниже (упрощено, например, для целей):
<?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 / Filter без какой-либо настройки ORM:
Call to a member function getClassMetadata() on null
Приветствуются любые указатели.






Так что мне, наконец, удалось с этим разобраться. Это было так же просто, как создание моей собственной версии 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