Это определенно возможно, но в зависимости от вашего выбора вам нужно проделать больше работы, чтобы получить желаемый результат.
Я go с помощью специальной операции, так как это легче объяснить, и у меня уже есть код примеры.
Чтобы получить информацию, необходимую для фильтрации, вам потребуется go с более низким уровнем доступа. Ключевая часть, которую вы пропустили, заключается в том, что платформа API построена на основе Symfony, поэтому вы можете просто использовать Request
(для пользовательской операции) или RequestStack
(для поставщика данных), чтобы получить фильтры. .
Также, чтобы убедиться, что платформа API знает, как сериализовать данные, которые вы выводите (Statistics
объекты), вам необходимо использовать DTO .
Вот как выглядит код:
В вашей сущности мы добавляем класс настраиваемой операции и указываем вывод как класс статистики:
* @ApiResource(
* ...
* itemOperations={
* "get_statistics"={
* "method"="GET",
* "path"="/users/{id}/statistics",
* "controller"=UserStatsAction::class,
* "input"=Statistics::class
* }
* },
* ...
*/
Пример кода настраиваемой операции:
final class UserStatsAction
{
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function __invoke(Request $request)
{
$id = $request->get('id');
$repository = $this->em->getRepository(User::class);
if(!($user = $this->repository->find($id))) {
throw new NotFoundHttpException();
}
$sports = $request->query->get('sport', []);
$outcome = $request->query->get('outcome');
// Optional: validate your filter data
$validator = Validation::createValidator();
$context = $validator->startContext();
$context->atPath('sports')->validate($sports, [
new Assert\Choice([
'choices' => ['football', 'basketball'],
]),
]);
$context->atPath('outcome')->validate($outcome, [
new Assert\Choice([
'choices' => ['win', 'loose', 'tie'],
]),
]);
$violations = $context->getViolations();
if (0 !== count($violations)) {
throw new ValidationException($violations);
}
// I'll assume you are hnadiling empty/nulls value properly inside this method
// and return all the stats if
$results = $repository->getStatistics($sports, $outcome);
// For this to work, you'll need to set a DTO for your stats
return $results;
}
}
Не. Я использую Request
в качестве аргумента для настраиваемой операции, а не сущность User
. В моем примере есть код, который может вам не понадобиться, например, выборка пользователя из репозитория или проверка фильтров (хотя я делаю поощряю очистку / проверку ввода пользователя).
Одно важное упоминание : пользовательские операции не поддерживаются платформой API, и вы потеряете поддержку GraphQL. Если вам нужен GraphQL, того же результата можно добиться с помощью DataProvider
, но это более сложная настройка, и мне нужно будет смоделировать некоторые части вашего приложения, чтобы понять это.
Надеюсь, это поможет.
Обновление:
Чтобы фильтры работали, вам также необходимо обновить конфигурацию OpenAPI / Swagger, как tobias ingold указано в комментарии ниже.
Вы можете сделать это, используя PHP и создав нормализатор, как описано в разделе Переопределить спецификацию OpenAPI документации.
Это также может быть сделано путем расширения аннотации APIResource
, вот пример:
* @ApiResource(
* ...
* collectionOperations={
* "post",
* "get"={
* "openapi_context"={
* "parameters"={
* {
* "name": "<query_string_param_name>",
* "type": "string",
* "in": "query",
* "required": false,
* "description": "description",
* "example": ""
* }
* }
* }
* }
* }
* ...
* })
Я нашел этот подход более простым в использовании, но он не задокументирован. Я экстраполировал это на основе своих знаний об OpenAPI spe c и примера Настройка объекта, получающего загруженный файл в официальной документации.