为了实现路由版本控制以及实体与 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 属性
我一直在寻找同样的东西,我发现它从 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