API平台增加了对非实体资源的过滤和分页



为了路由版本控制和更好地分离实体和api输出,我创建了一个不是实体的资源,它不是由提供商链接到实体的。我想添加一些过滤器和分页,但似乎我不能本地。

例如,我有一个实体:
<?php
namespace AppEntity;
use AppRepositoryUserApiKeyRepository;
use DoctrineDBALTypesTypes;
use DoctrineORMMapping as ORM;
use GedmoBlameableTraitsBlameableEntity;
use GedmoMappingAnnotation as Gedmo;
use GedmoTimestampableTraitsTimestampableEntity;
#[ORMEntity(repositoryClass: TreasureRepository::class)]
#[GedmoSoftDeleteable(fieldName: 'deletedAt', timeAware: true, hardDelete: false)]
class Treasure
{
use BlameableEntity;
use TimestampableEntity;
#[ORMId]
#[ORMGeneratedValue]
#[ORMColumn]
private int $id;
#[ORMManyToOne(inversedBy: 'treasures')]
#[ORMJoinColumn(referencedColumnName: 'owner_id', nullable: false)]
private Owner $owner;
#[ORMColumn(length: 255)]
private string $name;
#[ORMColumn(type: Types::DECIMAL, precision: 10, scale: 2)]
private string $value;
#[ORMColumn(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?DateTimeInterface $deletedAt = null;

我做了一个资源:

<?php
namespace AppApiResourceV1;
use ApiPlatformMetadataApiResource;
use ApiPlatformMetadataDelete;
use ApiPlatformMetadataGet;
use ApiPlatformMetadataGetCollection;
use ApiPlatformMetadataLink;
use ApiPlatformMetadataPost;
use AppEntityOwner;
#[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;
}
}

这样我既没有分页也没有过滤器。如果我在name上添加过滤器属性例如

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

出错

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

另外,我试图在我的提供程序中添加一个不能很好地工作的分页,我没有"hydra: totalitem "的实际结果显示当前页面的总数,而不是所有结果,并且我没有json- old提供的前一页、下一页和总页面信息。我没有看到用数据设置ApiPlatform分页的方法。

这是我的提供商的一个示例:

$owner = $this->ownerRepository->find($uriVariables['owner_id']);
/** ApiPlatformStatePaginationPagination $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属性开箱即用,即使用这种方式编码

我正在寻找相同的东西,我发现它现在从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