如何获取 API- 加载相关平台(例如 Many2One)resources/entities?
How to get API-Platform to load related (e.g. Many2One) resources/entities?
根据documentation,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
:
/**
* 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
:
中写了这个
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" 应该是实际实体,急切加载,但只返回 IRI。我确认执行的 SQL 查询不包括任何类型的 join
.
有趣的是,这似乎是与this other user is having相反的麻烦。我希望我有他们的问题。
是什么阻止了这些关系被急切加载?关系以其他方式工作(我可以使用 Doctrine 进行其他查询,或创建自定义序列化组,相关属性将被包括在内)。
默认dereferenceable IRIs用于显示相关关联。
查看执行的语句,您应该看不到明确的 JOIN
查询,而是相关关联的附加 SELECT
语句。
如果您想要关联对象的 JSON 表示。
您需要在相关关联中为所需属性指定 Serialization
@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"
}
根据documentation,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
:
/**
* 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
:
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" 应该是实际实体,急切加载,但只返回 IRI。我确认执行的 SQL 查询不包括任何类型的 join
.
有趣的是,这似乎是与this other user is having相反的麻烦。我希望我有他们的问题。
是什么阻止了这些关系被急切加载?关系以其他方式工作(我可以使用 Doctrine 进行其他查询,或创建自定义序列化组,相关属性将被包括在内)。
默认dereferenceable IRIs用于显示相关关联。
查看执行的语句,您应该看不到明确的 JOIN
查询,而是相关关联的附加 SELECT
语句。
如果您想要关联对象的 JSON 表示。
您需要在相关关联中为所需属性指定 Serialization
@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"
}