2016-06-24 32 views
0

好吧,一句話:幫助!ZF2項目中的原則2延遲加載問題

有一些我不明白。在ZF2中,我使用了很棒的Doctrine Orm模塊。一切都很完美,但今天我發現了一些奇怪的東西。 我想我的某處肯定有一些錯誤,但我找不到。或者,也許有一些我不明白在學說2中。

我有我的實體映射。當我沒有指定獲取選項時有多對一關係時,當通過調用我的存儲庫上的find()方法獲得一個實體時,我可以看到我的屬性包含預期的代理類實例。但是當我在該屬性上調用setter時,它仍然包含代理類的emtpy實例?

看來,學說不能得到實體鏈接到我的實體。就我而言,我從find()方法獲得的實體是關係的所有者。

如果我在映射中指定了EAGER上的fetch選項,那麼調用find()方法將返回一個實體,該實體的屬性包含按預期方式包含在關係中指定的類的實例。

有人曾經有過同樣的問題嗎?

編輯: 好吧,我創建了一個新的ZF2項目,以確保沒有任何干擾。 所以,我有兩個實體組和用戶:

/** 
* Class Group 
* @package Application\Entity 
* @Entity 
* @Table("`group`") 
*/ 
class Group 
{ 
    /** 
    * @Id 
    * @GeneratedValue 
    * @Column(type="integer", options={"unsigned"=true}) 
    */ 
    private $id; 

    /** 
    * @Column(type="string") 
    */ 
    private $name; 

    /** 
    * @OneToMany(targetEntity="User", mappedBy="group") 
    */ 
    private $users; 
} 

/** 
* Class User 
* @package Application\Entity 
* @Entity 
* @Table(name="user") 
*/ 
class User 
{ 
    /** 
    * @Id 
    * @GeneratedValue 
    * @Column(type="integer", options={"unsigned"=true}) 
    */ 
    private $id; 

    /** 
    * @Column(type="string") 
    */ 
    private $firstName; 

    /** 
    * @Column(type="string") 
    */ 
    private $lastName; 

    /** 
    * @ManyToOne(targetEntity="Group", inversedBy="users") 
    * @JoinColumn(name="groupId", referencedColumnName="id") 
    */ 
    private $group; 
} 

當然,我有兩個類中的所有getter和setter,但我並沒有把他們的例子走快。

在我控制我做一個很簡單的事情來測試,而不認爲:

$user = $this->serviceLocator->get('doctrine.entitymanager.orm_default')->getRepository('Application\Entity\User')->find(1); 
var_dump($user->getGroup());exit; 

後續代碼var_dump顯示:

object(DoctrineORMModule\Proxy\__CG__\Application\Entity\Group)[367] 
    public '__initializer__' => 
    object(Closure)[362] 
    public '__cloner__' => 
    object(Closure)[363] 
    public '__isInitialized__' => boolean false 
    private 'id' (Application\Entity\Group) => int 1 
    private 'name' (Application\Entity\Group) => null 

當然,我在數據庫中的用戶和組,我加入有一個用戶在表組中有一個id爲1的用戶。

也許我錯過了一個選擇或什麼?爲了配置Doctrine模塊,我只是遵循github上的文檔,所以在這裏我給了我的實體的註釋驅動程序和目錄,當然還有數據庫憑證。

+0

這聽起來像是你錯過了一些相當簡單的事情,但是沒有更多的細節是不可能分辨出來的。你可以通過顯示一些代碼來改善你的問題,特別是相關的映射指令和你的資源庫的使用情況。 – timdev

+0

好吧,我添加了一些細節:我創建了一個小型項目,以確保每件事情都很乾淨。我把我的實體代碼和我的測試。再一次,如果我把組件關係的用戶實體中的fetch =「EAGER」,每件事情都很好。但沒有它... – Bruce

+1

乍看起來很好看。那麼接下來會發生什麼?當doe「在該屬性上調用setter時,它仍然包含代理類的emtpy實例」會發生什麼? – timdev

回答

2

這是完全預期的行爲,因爲教條是延遲加載您的組實體。這是因爲所有你要做的是:

$user->getGroup(); 

我會嘗試解釋爲什麼你只得到這裏的代理:

你已經從數據庫解決User實體持有的標識符(在這種情況下id = 1 )爲您的團體實體(此ID來自user表中的groupId列)。當您致電getGroup時,doctrine只爲您的Group實體創建一個代理,並將其id設置爲1。到目前爲止,無需進行數據庫交互。

由於您不需要從您的Group實體請求任何其他內容,因此在這種簡單情況下,代理就足夠了。您從組實體請求另一個屬性(任何其他直接屬性(組表中的一列),但是標識符)時,您會注意到一個差異。嘗試在您的羣組實體上撥打getName()。該屬性尚未加載,因此doctrine將從數據庫中的group表中獲取id = 1的行,並將加載組對象內的所有列作爲屬性(在這種情況下只有一個),然後它將返回請求的名字。

所以一次嘗試這樣的:

$user->getGroup()->getName(); 

而且你的輸出就會有很大的不同。

我希望這可以讓行爲更容易理解。

+0

是的。事實上,我今天決定看一看由教條生成的代理類,我可以看到這一點。我錯誤地理解了由於閱讀速度很快而引起的延遲加載方式,起初我認爲調用關係上的getter對於教條啓動延遲加載就足夠了。但確實有必要訪問一個屬性。謝謝你的解釋 – Bruce