如何获得API平台来加载相关(例如Many2One)资源/实体? [英] How to get API-Platform to load related (e.g. Many2One) resources/entities?

查看:114
本文介绍了如何获得API平台来加载相关(例如Many2One)资源/实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据api 文档平台默认会急于加载相关资源。

According to the documentation, api-platform will eager-load related resources by default.

但是在默认配置下,我对资源的所有查询都具有关联性(大多数情况下是典型的 Many2One 关系)用对象IRI而不是序列化的对象填充这些属性。

But on the default configuration, all my queries to resources with relations (mostly with typical Many2One relationships) populate these properties with the object IRI instead of the serialized object.

例如,对于该实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\BoostLeadContactActionRepository")
 * @ORM\Table(name="BoostLeadContactActions")
 */
class BoostLeadContactAction {

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\BoostLead", inversedBy="contacts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $boostLead;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\ContactChannel", fetch="EAGER")
     * @ORM\JoinColumn(nullable=false, referencedColumnName="Id")
     */
    private $channel;

    // getters/setters/extra properties removed for brevity
}

然后我们有相应的 ContactChannel

/**
 * ContactChannel
 *
 * @ORM\Table(name="ContactChannels")
 * @ORM\Entity
 */
class ContactChannel {

    /**
     * @var int
     *
     * @ORM\Column(name="Id", type="smallint", nullable=false, options={"unsigned"=true})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Name", type="string", length=64, nullable=false)
     */
    private $name = '';
}

我已设置 fetch = EAGER 关系,即使理论上是不需要的。我的配置是默认配置,以防万一我实际上是在 api_platform.yaml 中写了这个:

I've set up fetch="EAGER" on the relationship even if in theory is not needed. My configuration is the default, but just in case I actually wrote this in my api_platform.yaml:

    eager_loading:
        # To enable or disable eager loading.
        enabled: true

        # Fetch only partial data according to serialization groups.
        # If enabled, Doctrine ORM entities will not work as expected if any of the other fields are used.
        fetch_partial: false

        # Max number of joined relations before EagerLoading throws a RuntimeException.
        max_joins: 30

        # Force join on every relation.
        # If disabled, it will only join relations having the EAGER fetch mode.
        force_eager: true

debug:config api_platform 确认已应用正确的配置:

The result of debug:config api_platform confirms the correct configuration is applied:

Current configuration for extension with alias "api_platform"
=============================================================

api_platform:
    title: FooBar API
    description: 'FooBar API, only for authenticated use'
    version: 0.8.0
    name_converter: null
    path_segment_name_generator: api_platform.path_segment_name_generator.underscore
    eager_loading:
        enabled: true
        fetch_partial: false
        max_joins: 30
        force_eager: true

但是结果将是这样的:

And yet the results will be something like:

{
  "@context": "/api/contexts/BoostLeadContactAction",
  "@id": "/api/boost_lead_contact_actions/9",
  "@type": "BoostLeadContactAction",
  "id": 9,
  "boostLead": "/api/boost_leads/30",
  "channel": "/api/contact_channels/1",
  "direction": "outgoing",
  "successful": true,
  "type": "/api/lead_contact_attempt_reasons/1",
  "notes": "2",
  "createdAt": "2019-05-16T10:27:33+00:00",
  "updatedAt": "2019-05-16T10:27:33+00:00"
}

boostLead, channel和 type应该是实际的实体,并且急切地加载,但仅而是返回IRI。我确认执行的SQL查询不包含任何类型的 join

"boostLead", "channel" and "type" should be actual entities, eagerly loaded, but only IRIs are returned instead. I confirmed that the SQL query performed does not include any kind of join.

有趣的是,似乎与其他用户遇到的问题相反。我希望我能遇到他们的问题。

Funnily enough, it seems to be the opposite trouble than this other user is having. I wish I had their problems.

是什么能阻止这些关系急于得到解决?否则关系将起作用(我可以使用Doctrine进行其他查询,或创建自定义序列化组,并将包含相关属性)。

What could be preventing these relationships to be loaded eagerly? The relationships work otherwise (I can do other queries with Doctrine, or create custom serialization groups and the related properties will be included).

推荐答案

默认情况下,可引用的IRI 用于显示相关的关联。
查看执行的语句,您应该不会看到显式的 JOIN 查询,而应该看到附加的 SELECT 语句。相关的关联。

By default dereferenceable IRIs are used to display the related associations. Looking at the executed statements you should not see an explicit JOIN query but rather additional SELECT statements for the related associations.

如果您想要关联对象的JSON表示形式。
您需要为相关关联中的所需属性指定序列化 @Groups
这将导致 SELECT 语句添加 JOIN 来检索要序列化的相关数据。

If you are wanting the JSON representation of the associated object. You need to specify the Serialization @Groups for the desired properties in the related association. This will cause the SELECT statement to add in a JOIN to retrieve the related data to be serialized.

有关更多详细信息,请参见 https://api-platform.com/docs/core/serialization/#embedding-relations

For more details see https://api-platform.com/docs/core/serialization/#embedding-relations

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(normalizationContext={ "groups": {"boost"} })
 * @ORM\Entity()
 * @ORM\Table(name="BoostLeadContactActions")
 */
class BoostLeadContactAction {

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups({"boost"})
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\BoostLead", inversedBy="contacts")
     * @ORM\JoinColumn(nullable=false)
     * @Groups({"boost"})
     */
    private $boostLead;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\ContactChannel", fetch="EAGER")
     * @ORM\JoinColumn(nullable=false, referencedColumnName="Id")
     * @Groups({"boost"})
     */
    private $channel;

    // getters/setters/extra properties removed for brevity
}





namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource()
 * @ORM\Table(name="ContactChannels")
 * @ORM\Entity
 */
class ContactChannel {

    /**
     * @var int
     * @ORM\Column(name="Id", type="smallint", nullable=false, options={"unsigned"=true})
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @Groups({"boost"})
     */
    private $id;

    /**
     * @var string
     * @ORM\Column(name="Name", type="string", length=64, nullable=false)
     * @Groups({"boost"})
     */
    private $name = '';
}

应该导致检索归一化值

{
  "@context": "/api/contexts/BoostLeadContactAction",
  "@id": "/api/boost_lead_contact_actions/9",
  "@type": "BoostLeadContactAction",
  "id": 9,
  "boostLead": "/api/boost_leads/30",
  "channel": {
      "@id": "/api/contact_channels/1",
      "@type": "ContactChannel",
      "id": "1",
      "name": "Test"
   },
  "direction": "outgoing",
  "successful": true,
  "type": "/api/lead_contact_attempt_reasons/1",
  "notes": "2",
  "createdAt": "2019-05-16T10:27:33+00:00",
  "updatedAt": "2019-05-16T10:27:33+00:00"
}

这篇关于如何获得API平台来加载相关(例如Many2One)资源/实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆