当前位置: 首页 > 知识库问答 >
问题:

如何让API平台加载相关(如多个)资源/实体?

暨高洁
2023-03-14

根据文档,默认情况下,api平台将加载相关资源。

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

例如,对于该实体:

/**
 * @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
 *
 * @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 = '';
}

我已经在关系上设置了finch="EAGER",即使理论上不需要。我的配置是默认的,但是以防万一我真的在我的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的结果确认应用了正确的配置:

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

然而结果会是这样的:

{
  "@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”应该是实际的实体,急切地加载,但只返回IRIs。我确认所执行的SQL查询不包括任何类型的连接。

有趣的是,这似乎是另一个用户遇到的相反的麻烦。我希望我有他们的问题。

是什么阻止了这些关系被急切地加载?这些关系以其他方式工作(我可以使用Doctrine进行其他查询,或者创建自定义序列化组,相关属性将被包括在内)。


共有1个答案

岳佐
2023-03-14

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

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

更多详情见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"
}

 类似资料:
  • 我需要创建一个GETendpoint来返回通过超文本传输协议客户端从另一个应用程序获取的资源,而不是基于实体。我获取的资源是一个数组: 然后我需要查询数据库以获取一些数据以添加到资源数组中。 所以我在中创建了它: 但是现在,我希望我的api返回json api响应格式:https://jsonapi.org/. 基于实体的资源,api平台完全支持。我不需要做太多。我只是在实体类中添加“key”并配

  • 我有一个包含 Serie 对象的集合的 Chart 对象,这些 Serie 对象包含数据对象的集合。我希望根据它们在各自集合中的位置来标识 REST API 来识别 Serie 和 Data 对象,而不是要求 REST API 通过代理主键来识别 Serie 和 Data 对象。 数据库模式如下。最初我考虑使serie的和data的复合主键,但是,Doctrine只能对一个级别(即Serie)这样

  • 我正在开发我的第一个RESTful api,这(不幸的是)是在一个已经存在的系统上完成的,想法是允许第三方访问这个系统。 一切都很好,直到我意识到我有多种方法来访问相同的资源。我将尝试使用系统的一部分来解释它。该系统是使用Laravel 5.8构建的,其中包括以下数据库表: 用户 电子邮件 短信 每个用户可以有许多电子邮件,并且每个电子邮件只属于一个用户。这同样适用于短信。 我“忽略”了当前的所有

  • 随着 Jekyll 被更广泛的使用,一系列的教程、框架、扩展、示例和其他各种有用的资源也相继出现。下面列出了一些最流行的 Jekyll 资源合辑的链接。 Jekyll 提示和技巧,以及示例 与 GitHub Pages 集成的技巧 重用代码并保持文档同步至最新的示例。 使用 Simple Form 来集成一个简单的联系表单 JekyllBootstrap.com 提供了详细的解释,例子和辅助代码让

  • Windows 命令行界面 cmder 的官方网站 宁皓网《命令行》视频课程 宁皓网《我的工作流程:Windows》视频课程里的命令行 宁皓网《我的工作流程》视频课程里的终端

  • Atlassian:Learn Git Git 远程服务 Github,国外服务商,公开仓库免费,私有仓库收费 Coding.net,国内服务商,提供免费的公开与私有仓库 阿里云 Git,国内服务商,提供免费的公开与私有仓库 Atlassian,国外服务商,提供免费的公开与私有仓库