标签: api-platform.com

如何使用 PHP 从 ApiPlatform 反序列化 JSON-LD

我已经使用 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 …

serialization symfony api-platform.com

5
推荐指数
0
解决办法
1988
查看次数

过滤一对多集合

我目前正在尝试过滤我的 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)

symfony doctrine-orm api-platform.com

5
推荐指数
0
解决办法
421
查看次数

自定义过滤器 API 平台不起作用

我正在尝试在 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-platform.com

5
推荐指数
1
解决办法
7383
查看次数

与api平台的嵌入关系

我的疑问是关于 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)

symfony api-platform.com symfony4

5
推荐指数
1
解决办法
7959
查看次数

Symfony / API 平台 - 自定义操作 - 使用 VichUploaderBundle 进行文件替换的 PUT 方法

我将 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)

php rest symfony vichuploaderbundle api-platform.com

5
推荐指数
1
解决办法
2539
查看次数

通过虚拟财产 API 平台进行 OrderFilter(排序)

    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”虚拟属性进行排序。如何实现按属性 …

php symfony api-platform.com

5
推荐指数
0
解决办法
1327
查看次数

API平台按空值过滤

我正在寻找一种解决方案来根据为空的参数(用户)恢复 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)

api symfony api-platform.com

5
推荐指数
1
解决办法
4281
查看次数

API Platform Symfony:仅获得 30 个结果(分页)

我正在将 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 的限制?

api symfony api-platform.com

5
推荐指数
1
解决办法
6849
查看次数

如何在 Api-Platform 中引入虚拟财产的过滤功能?

我正在使用 Symfony 5 和 API 平台。

我的一个类有一个通过侦听器设置的属性postLoad。该属性仅在某些条件下设置(否则为NULL),我希望允许 REST API 用户根据该属性是否为空或有值来过滤资源。

因为虚拟属性没有持久化到数据库中,所以我假设没有任何 Doctrine 过滤器(例如 )ExistsFilter将对该属性起作用。

如何使用 Symfony 5 和 API 平台为虚拟属性创建过滤功能?

php symfony api-platform.com symfony5

5
推荐指数
1
解决办法
986
查看次数

使用 DataProvider 维护分页来过滤 api 平台中的集合

我们实现了一个RolePermissionChecker,它应该控制特定资源的安全性/可访问性 ( Offer) 比较资源的访问者和创建者的属性。因为itemOperations我们正在使用Voterhttps://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)

php pagination symfony api-platform.com

5
推荐指数
0
解决办法
1081
查看次数