Symfony 4:调用 getter 后,Doctrine2 LAZY Fetch Collection 仍然为空
Posted
技术标签:
【中文标题】Symfony 4:调用 getter 后,Doctrine2 LAZY Fetch Collection 仍然为空【英文标题】:Symfony 4 : Doctrine2 LAZY Fetch Collection still empty after calling the getter 【发布时间】:2020-06-04 15:20:47 【问题描述】:我对某些实体有疑问:根据the doctrine documentation,延迟加载应该只允许我在调用 getter 时加载我的集合,但它没有。
这是关系描述:
一个位置有许多场地,由位置“externalId”字段映射。
这是我的实体及其关系的简化代码示例:
// Location.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\LocationRepository")
* @ORM\Table(name="Location")
*/
class Location extends Entity
/**
* @var integer
* @ORM\Column(type="integer", unique=true, nullable=true)
*/
protected $locationId;
/**
* @var integer
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer", nullable=false)
*/
protected $externalId;
/**
* @var Venue[]|Collection
* @ORM\OneToMany(targetEntity="App\Entity\Venue", mappedBy="locationExternalId", orphanRemoval=true, fetch="LAZY")
*/
protected $venues;
/**
* Location constructor.
* @param array $data
*/
public function __construct(array $data)
$this->venues = new ArrayCollection;
$this->hydrate($data);
/**
* @return int
*/
public function getLocationId()
return $this->locationId;
/**
* @param int $locationId
* @return $this
*/
public function setLocationId($locationId)
$this->locationId = $locationId;
return $this;
/**
* @return Venue[]|Collection
*/
public function getVenues()
return $this->venues;
/**
* @param Venue[]|Collection $venues
* @return $this
*/
public function setVenues($venues)
$this->venues = $venues;
return $this;
// Venue.php
namespace App\Entity;
use App\Entity\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\VenueRepository")
* @ORM\Table(name="Venue", indexes=@ORM\Index(name="IDX_Venue", columns="location_id"))
*/
class Venue extends Entity
/**
* @var integer
* @ORM\Column(type="integer", unique=true, nullable=true)
*/
protected $venueId;
/**
* @var integer
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer", nullable=false)
*/
protected $externalId;
/**
* @var Location
* @ORM\ManyToOne(targetEntity="App\Entity\Location", inversedBy="venues")
* @ORM\JoinColumn(name="location_external_id", referencedColumnName="external_id", nullable=true)
*/
protected $locationExternalId;
/**
* Venue constructor.
* @param array $data
*/
public function __construct(array $data)
$this->hydrate($data);
/**
* @return int
*/
public function getVenueId()
return $this->venueId;
/**
* @param int $venueId
* @return $this
*/
public function setVenueId($venueId)
$this->venueId = $venueId;
return $this;
/**
* @return int
*/
public function getExternalId()
return $this->externalId;
/**
* @param int $externalId
* @return $this
*/
public function setExternalId($externalId)
$this->externalId = (int)$externalId;
return $this;
/**
* @return Location
*/
public function getLocationExternalId()
return $this->locationExternalId;
/**
* @param Location $locationExternalId
* @return $this
*/
public function setLocationExternalId($locationExternalId)
$this->locationExternalId = $locationExternalId;
return $this;
如果我加载一个位置,场地没有初始化,这是预期的:
// Controller.php
use App\Entity\Basketball\Location;
use App\Entity\Basketball\Venue;
$location = $this->getDoctrine()->getRepository(Location::class)->findOneBy(['externalId' => 1]);
dump($location);
// Dump results
App\Entity\Location #1438 ▼ #locationId: 1644
#externalId: 1
#venues: Doctrine\ORM\PersistentCollection #1450 ▼
-snapshot: []
-owner: App\Entity\Location #1438
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager #75 …11
-backRefFieldName: "locationExternalId"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata #1441 …
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection #1700 ▶
#initialized: false
但它应该通过调用 getter,它没有按预期工作
// Controller.php
dump($location->getVenues());
// Dump results
Doctrine\ORM\PersistentCollection #1450 ▼
-snapshot: []
-owner: App\Entity\Location #1438 ▶
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager #75 …11
-backRefFieldName: "locationExternalId"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata #1441 …
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection #1700 ▼
-elements: []
#initialized: false
环境
Symfony v4.4.7 Doctrine v2.7 ("doctrine/doctrine-fixtures-bundle": "^3.3") 通过指定“fetch=EAGER”,它可以工作,但我不想...有什么想法吗?我应该怎么做才能初始化我的收藏?
编辑
感谢this Github issue 我找到了一种解决方法,方法是在 getter 中初始化集合,但仍然如此;应该有一种方法可以自动完成:
public function getVenues()
$this->venues->initialize();
return $this->venues;
【问题讨论】:
【参考方案1】:真的需要你吗?要初始化集合,您需要调用此集合的某些方法。如果您使用JMSSerializer
或Symfony Serializer
,您可以只返回序列化的数据,序列化程序会为您完成所有工作,因为它们调用toArray
方法来初始化您的集合。
【讨论】:
嗯,非常感谢,你是对的。文档不清楚,但“首次访问”意味着调用集合的方法。我不使用 JMSSerializer 或 Symfony Serializer,但我可以手动调用 toArray 方法,它工作正常:$location->getVenues()->toArray();
以上是关于Symfony 4:调用 getter 后,Doctrine2 LAZY Fetch Collection 仍然为空的主要内容,如果未能解决你的问题,请参考以下文章
Symfony、nelmio/api-doc-bundle 和 @SWG\SecurityScheme
Nelmio API 文档区域和带有 symfony 4 的不记名令牌
使用 Symfony 2 CLI 工具,如何为子类生成具有正确类型提示的 getter 和 setter?
Symfony Upload doc, docx file using sfValidatorFile Mime type issue