API平台对非实体资源添加过滤和分页

问题描述 投票:0回答:1

为了实现路由版本控制以及实体与 api 输出之间更好的分离,我创建了一个不是由提供者链接到该实体的实体的资源。 A 想要添加一些过滤器并进行分页,但似乎我本身就不能。

我有一个实体:

<?php

namespace App\Entity;

use App\Repository\UserApiKeyRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Blameable\Traits\BlameableEntity;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;

#[ORM\Entity(repositoryClass: TreasureRepository::class)]
#[Gedmo\SoftDeleteable(fieldName: 'deletedAt', timeAware: true, hardDelete: false)]
class Treasure
{
use BlameableEntity;

use TimestampableEntity;

#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private int $id;

#[ORM\ManyToOne(inversedBy: 'treasures')]
#[ORM\JoinColumn(referencedColumnName: 'owner_id', nullable: false)]
private Owner $owner;

#[ORM\Column(length: 255)]
private string $name;

#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 2)]
private string $value;

#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?\DateTimeInterface $deletedAt = null;

我做了一个资源:

<?php

namespace App\ApiResource\V1;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Link;
use ApiPlatform\Metadata\Post;
use App\Entity\Owner;

#[ApiResource(
    uriTemplate: '/owners/{owner_id}/treasures/{id}.{_format}',
    shortName: 'Treasures',
    operations: [
        new Get(),
        new Delete(
            processor: TreasureProcessor::class
        )
    ],
    uriVariables: [
        'owner_id' => new Link(
            fromProperty: 'treasures',
            fromClass: Owner::class
        ),
        'id' => new Link(
            fromClass: self::class
        )
    ],
    provider: TreasureProvider::class
)]
#[ApiResource(
    uriTemplate: '/owners/{owner_id}/treasures.{_format}',
    shortName: 'Treasures',
    operations: [
        new GetCollection(
            normalizationContext: ['groups' => 'list']
        ),
        new Post(
            denormalizationContext: ['groups' => 'create'],
            processor: TreasureProcessor::class,
        )
    ],
    uriVariables: [
        'owner_id' => new Link(
            fromProperty: 'treasures',
            fromClass: Owner::class
        )
    ],
    provider: TreasureProvider::class
)]
class TreasureResource
{
    #[Groups(['list'])]
    private ?int $id;
    #[Groups(['list', 'create'])]
    private string $name;
    #[Groups(['list', 'create'])]
    private string $value;
    private ?Owner $owner;

    public function __construct(
        string $name,
        string $value,
        ?Owner $owner = null,
        ?int $id = null
    )
    {
        $this->id = $id;
        $this->name = $name;
        $this->value = $value;
        $this->owner = $owner;
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getValue(): string
    {
        return $this->value;
    }

    public function getOwner(): ?Owner
    {
        return $this->owner;
    }
}

就像我没有分页也没有过滤器。 例如,如果我在名称上添加过滤器属性

#[ApiFilter(SearchFilter::class, strategy: 'partial')]

我有一个错误

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

此外,我尝试在我的提供程序中添加分页,但效果不佳,我没有“Hydra:totalItems”的真实结果,该结果显示当前页面的总计而不是所有结果,而且我没有上一页、下一页、总页数信息由 json-ld 提供。 我没有找到用数据设置 ApiPlatform 分页的方法。

这是我的提供商的示例:

$owner = $this->ownerRepository->find($uriVariables['owner_id']);

/** ApiPlatform\State\Pagination\Pagination $this->pagination */
$page = $this->pagination->getPage($context);
$itemsPerPage = $this->pagination->getLimit($operation, $context);

$treasures = $this->treasureRepository->findByOwnerPaginated($owner, $page, $itemsPerPage);

return $this->collectionToResources($treasures); //returns an array

有人遇到过这些问题并能够解决或绕过它们吗?我希望即使使用这种编码方式也可以开箱即用地使用 ApiPlatform 属性

php symfony api-platform.com
1个回答
0
投票

我一直在寻找同样的东西,我发现它从 v3.1.8 开始就可用了。要实现它,您必须使用

stateOptions
:

#[ApiResource(
    operations: [
        new Get(
            uriTemplate: '/entityClassAndCustomProviderResources/{id}',
            uriVariables: ['id']
        ),
        new GetCollection(
            uriTemplate: '/entityClassAndCustomProviderResources'
        ),
    ],
    provider: EntityClassAndCustomProviderResourceProvider::class,
    stateOptions: new Options(entityClass: SeparatedEntity::class)
)]
class EntityClassAndCustomProviderResource

源代码:https://github.com/api-platform/core/pull/5550/files#diff-15a5e5dac807773e03253202f2a43d4e695aa7ac2f43874116741a6d9b4c69ca

© www.soinside.com 2019 - 2024. All rights reserved.