Symfony 4:Doctrine2 LAZY Fetch Collection在调用getter之后仍然为空

问题描述 投票:0回答:1

我对某些实体有问题:根据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(“教义/教义-夹具-捆绑”:“ ^ 3.3”)
  • 通过指定“ fetch = EAGER”,它可以工作,但是我不想...

有什么想法吗?我应该怎么做才能初始化我的收藏集?

编辑

由于this Github issue,我找到了一种解决方法,方法是在getter内初始化集合,但仍然如此;应该有一种自动执行的方法:

public function getVenues()
{
    $this->venues->initialize();
    return $this->venues;
}
orm doctrine symfony4
1个回答
0
投票

真的需要吗?为了初始化集合,您需要调用该集合的某些方法。如果您使用的是JMSSerializerSymfony Serializer,则只需返回序列化的数据,序列化程序将为您完成所有工作,因为它们调用了toArray方法来初始化您的集合。

© www.soinside.com 2019 - 2024. All rights reserved.