symfony API平台在非实体资源上添加过滤器和分页

b09cbbtk  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(114)

为了路由版本化和实体与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属性开箱即用,即使这种编码方式

h79rfbju

h79rfbju1#

我一直在寻找同样的东西,我发现它现在可以从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

相关问题