我已经使用 ApiPlatform 成功为我的系统构建了一个 API。感谢开发人员,这是一个出色的系统。我可以以 JSON-LD 格式向它发送请求,它也以 JSON-LD 格式返回响应。
我了解使用 JSON-LD 的好处,但我觉得我错过了一大块拼图。如何在我基于 Symfony 的 PHP 客户端(使用 API)中使用嵌入式 JSON-LD 上下文反序列化为 PHP 对象。
假设我的 API 有以下响应
{
"@context": "/contexts/CallbackRequest",
"@id": "/callback-requests/72",
"@type": "CallbackRequest",
"id": 72,
"created": "2017-09-22T08:07:25+02:00",
"customer": {
"@id": "/customers/13",
"@type": "Customer",
"id": 13,
"firstName": "Joe",
"lastName": "Bloggs",
"email": "joe@bloggs.com",
"mobilePhone": "123456789"
}
}
Run Code Online (Sandbox Code Playgroud)
现在,由于 JSON-LD @context 和 @type 数据,这里有足够的信息可以反序列化为CallbackRequest
具有嵌套对象的2 个 PHP 对象。Customer
我已经编写了自己的反规范化器,但我必须告诉序列化器我想首先反序列化为哪种对象,但如果不首先对其进行规范化,我无法从 JSON-LD 中提取它。
我进行了很多搜索,寻找为 Symfony 序列化器制作 JSON-LD 规范化器/反规范化器的人,但什么也没找到(除了 API 平台包本身内的此功能)。
任何人都可以向我提供任何指针,无论是我可以实现的 JSON-LD 非规范化程序包,还是有关如何实现 Symfony 序列化程序以对 JSON-LD …
我目前正在尝试过滤我的 OneToMany 集合结果,但运气不佳。
我已尝试按照此处文档中的说明设置过滤器,但无济于事。使用以下代码,我只能选择在Foos
集合/api/foos <- 上进行过滤的选项 <- 即使将分页设置为每页 1,此请求实际上也不会在应用过滤器后完成。
我希望/需要它位于/api/foos/1?bar.isRetired=false并返回 1 'Bar' 和许多 'foos' 的结果,但其中 'foo.isRetired = false'
// config/packages/api_filters.yaml
services:
filters.retired_filter:
parent: 'api_platform.doctrine.orm.boolean_filter'
arguments: [ { bars.isRetired: ~ } ]
tags: [ 'api_platform.filter' ]
// src/Entity/Foo.php
/* @ApiResource(attributes={"filters"={"filters.retired_filter"}}) */
class Foo
{
private $id;
private $name;
/** @ORM\OneToMany(targetEntity="Bars", mappedBy="foo") */
private $bars;
public function __construct(){
$this->bars = new ArrayCollection();
}
}
// src/Entity/Bar.php
/* @ApiResource() */
class Bar
{
private $id;
private …
Run Code Online (Sandbox Code Playgroud) 我正在尝试在 API 平台中实现自定义或过滤器。但由于某种原因,它没有加载。在我的配置下面找到。
这是我的过滤器:
<?php
namespace AppBundle\Filter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Common\Annotations\AnnotationReader;
final class SearchFilter extends AbstractFilter
{
protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
{
if ($property === 'search') {
$this->logger->info('Search for: ' . $value);
} else {
return;
}
$reader = new AnnotationReader();
$annotation = $reader->getClassAnnotation(new \ReflectionClass(new $resourceClass), \AppBundle\Filter\SearchAnnotation::class);
if (!$annotation) {
throw new \HttpInvalidParamException('No Search implemented.');
}
$parameterName = $queryNameGenerator->generateParameterName($property);
$search = [];
$mappedJoins = []; …
Run Code Online (Sandbox Code Playgroud) 我的疑问是关于 Api 平台的。( https://api-platform.com ) 我有两个实体。问题和答案。我想要进行一次 POST 调用来创建一个只有一个答案的问题。我展示我的实体。
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ApiResource(
* normalizationContext={"groups"={"question"}},
* denormalizationContext={"groups"={"question"}})
* @ORM\Entity
*/
class Question
{
/**
* @Groups({"question"})
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Groups({"question"})
* @ORM\Column
* @Assert\NotBlank
*/
public $name = '';
/**
* @Groups({"question"})
* @ORM\OneToMany(targetEntity="Answer", mappedBy="question", cascade={"persist"})
*/
private $answers;
public function getAnswers()
{
return $this->answers;
}
public function …
Run Code Online (Sandbox Code Playgroud) 我将 Vich Uploader Bundle 与 API Platform 结合使用来存储文件。我已按照官方文档https://api-platform.com/docs/core/file-upload/#handling-file-upload中的说明进行操作
一切正常,除了我想包含 PUT 调用来替换现有的 MediaObject 实体。我的尝试如下:
我创建了一个自定义操作并将其映射到实体中的 PUT 方法,如下所示:
<?php
// api/src/Entity/MediaObject.php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\CreateMediaObject;
use App\Controller\EditMediaObject;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity
* @ApiResource(
*
* ...
*
* itemOperations={
* "get",
* "put"={
* "controller"=EditMediaObject::class,
* "deserialize"=false,
* "validation_groups"={"Default", "media_object_create"},
* "swagger_context"={
* "consumes"={
* "multipart/form-data",
* },
* "parameters"={
* …
Run Code Online (Sandbox Code Playgroud) class SingleProduct extends AbstractEntity implements SingleProductEntityInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @Groups({"read", "get"})
*/
private $id;
/**
* @var string
* @ORM\Column(name="name", type="string", length=255, nullable=true)
* @Groups({"read", "get"})
*/
private $name;
/**
* @ORM\Column(name="main_han", type="string", length=20, nullable=true)
* @Groups({"read","get"})
*/
private $mainHan;
/**
* @ORM\Column(name="main_ean", type="string", length=13, nullable=true)
* @Groups({"read","get"})
*/
private $mainEan;
/**
* @Groups({"read","get"})
*/
private $nbCatalogs;
}
Run Code Online (Sandbox Code Playgroud)
在这个实体中,我正在 nbCatalogs 的 getter 中计算关系实体的数量。上述其他字段是数据库中的列。当我添加
@ApiFilter(OrderFilter::class, properties={"id", "name","mainHan","mainEan","nbCatalogs"}, arguments={"orderParameterName"="order"})
Run Code Online (Sandbox Code Playgroud)
我可以按 id、name、mainHan、mainEan 对 asc 和 desc 进行排序,但无法按我创建的“nbCatalogs”虚拟属性进行排序。如何实现按属性 …
我正在寻找一种解决方案来根据为空的参数(用户)恢复 get 中的数据:
{
"@context": "\/api\/contexts\/ShippingCost",
"@id": "\/api\/shipping_costs",
"@type": "hydra:Collection",
"hydra:member": [
{
"@id": "\/api\/shipping_costs\/1",
"@type": "ShippingCost",
"id": 1,
"minWeight": 0,
"maxWeight": 251,
"france": 4.87,
"domTom": 4.21,
"aerial": 3.84,
"zone": {
"@id": "\/api\/zones\/1",
"@type": "Zone",
"id": 1,
"name": "Guadeloupe",
"TaxFOB": 35,
"TaxSurete": 0.2,
"TaxFuel": 0.77,
"TaxGuerre": 0.24,
"Lta": 0,
"InfoDouane": 24,
"CreditEnlevement": 0,
"EntreposageCci": 0.4,
"EntreposageCciMin": 15,
"RemiseDoc": 43,
"Surete": 0,
"AvanceFond": 0,
"Tid": 13,
"Spia": 10,
"InterTransite": 50
},
"user": null
},
{
"@id": "\/api\/shipping_costs\/162",
"@type": "ShippingCost",
"id": 162, …
Run Code Online (Sandbox Code Playgroud) 我正在将 Symfony API 与 Angular 客户端结合使用。当尝试从报价表中获取数据时,当我想要获取所有内容时,最多只能得到 30 个结果。我在 API 上使用 Sellsy。在 SellsyService.php 中,我猜想当我尝试获取报价时会调用此函数:
public function getQuotations()
{
$devisRequest = array(
'method' => 'Document.getList',
'params' => array(
'doctype' => "estimate",
'pagination' => array(
'nbperpage' => 4999,
),
'search' => array(
//'steps' => ['sent','accepted']
'steps' => explode(
",",
"draft,due,payinprogress,paid,late,sent,read,accepted,contested,expired,advanced,partialinvoiced,invoiced,stored,spent,partialspend,refused"
),
),
),
);
$devislist = $this->sellsy->requestApi($devisRequest);
return $devislist;
}
Run Code Online (Sandbox Code Playgroud)
我真的不知道去哪里找,我没有开发这个API。当在项目中查找“30”时,我可以在缓存中看到:
'api_platform.eager_loading.max_joins' => 30,
'api_platform.collection.pagination.items_per_page' => 30,
Run Code Online (Sandbox Code Playgroud)
不知道跟我的问题有没有关系。这是配置 api_platform.yaml:
api_platform:
swagger:
api_keys:
apiKey:
name: Authorization
type: header
mapping:
paths: ['%kernel.project_dir%/src/Entity']
Run Code Online (Sandbox Code Playgroud)
我应该在哪里设置这个 30 的限制?
我正在使用 Symfony 5 和 API 平台。
我的一个类有一个通过侦听器设置的属性postLoad
。该属性仅在某些条件下设置(否则为NULL
),我希望允许 REST API 用户根据该属性是否为空或有值来过滤资源。
因为虚拟属性没有持久化到数据库中,所以我假设没有任何 Doctrine 过滤器(例如 )ExistsFilter
将对该属性起作用。
如何使用 Symfony 5 和 API 平台为虚拟属性创建过滤功能?
我们实现了一个RolePermissionChecker
,它应该控制特定资源的安全性/可访问性 ( Offer
) 比较资源的访问者和创建者的属性。因为itemOperations
我们正在使用Voter
(https://api-platform.com/docs/core/security/#hooking-custom-permission-checks-using-voters),它工作得很好。
根据https://api-platform.com/docs/core/security/#filtering-collection-according-to-the-current-user-permissions应该collectionOperations
DataProvider
使用 - 所以我们实现了一个。
我们现在遇到的问题是OfferCollectionDataProvider
首先调用它的父级ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider::getCollection
函数以应用所有扩展并检索集合。然后我们过滤用户无权读取的实体。但是,当我们在准备好的页面上使用分页和过滤时,分页随后就会被破坏,例如一半的页面条目将被过滤,对于用户来说,看起来好像没有更多数据了。
有谁知道如何在不破坏分页且不使用扩展的情况下过滤集合,因为我们的权限检查有点复杂并且很难转换为查询?
<?php
namespace App\DataProvider;
use ApiPlatform\Core\Bridge\Doctrine\Orm\CollectionDataProvider;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Paginator;
use App\Entity\Offer;
use App\Entity\User;
use App\Service\RolePermissionChecker;
use ArrayIterator;
use Doctrine\Persistence\ManagerRegistry;
use ReflectionProperty;
use Symfony\Component\Security\Core\Security;
/**
* Class OfferCollectionDataProvider
*
* @package App\DataProvider
*/
class OfferCollectionDataProvider extends CollectionDataProvider
{
/**
* @var RolePermissionChecker
*/
protected RolePermissionChecker $rolePermissionChecker;
/**
* @var Security $security
*/
protected Security $security;
/** …
Run Code Online (Sandbox Code Playgroud) api-platform.com ×10
symfony ×9
php ×4
api ×2
doctrine-orm ×1
pagination ×1
rest ×1
symfony4 ×1
symfony5 ×1