2012-02-21 13 views
9

我要救我的實體的一個對象到會話中,但因爲我這樣做,我得到以下兩個錯誤:Symfony2的連載實體對象的會話

例外: 的Symfony \捆綁\ FrameworkBundle \ DataCollector \ RequestDataCollector ::連載() 必須返回一個字符串或NULL

ErrorException:注意:串行ize():作爲成員返回的「id」 變量來自__sleep(),但不存在於 /var/www/clients/client71/web256/web/_dev_fd/kkupon/vendor/symfony/src/Symfony/Component/HttpKernel /DataCollector/DataCollector.php 線29

我的代碼是這樣的:

$offer = $this->getEntityManager()->getRepository('KkuponMainBundle:Offer')->find($offer_id); 
$request->getSession()->set('offer', $offer); 

我怎麼能得到它的權利?

謝謝。

UPDATE 在Rowgm的幫助下,我可以通過設置保護屬性而不是私人來解決這個問題。我唯一的問題是讀取 EntityManager不知道它的會話實體,如果我將對象(從會話)添加到另一個對象(它們之間有OneToMany關係),它不會工作。

<?php 
$offer = $this->get('session')->get('offer'); 
$coupon = new Coupon(); 
$coupon->setOffer($offer); 
$this->em->persist($coupon); 
$this->em->flush(); 

這就提出了一個錯誤,因爲優惠券上的對象屬性根據的EntityManager這不是在數據庫中(實際上它是在數據庫中,我投入到會議從DB)。

<?php 
$offer = $this->get('session')->get('offer'); 
echo $this->em->getUnitOfWork()->isInIdentityMap($offer) ? "yes":"no"; //result: no 

一種解決方案可以是: $offer = $this->em->merge($offer);

但這並不似乎是最好的之一。我希望我的EntityManager感知存儲在會話中的實體對象,而不必每次都告訴它。 有什麼想法?

回答

14

您可以通過將所有屬性和關係從專用設置爲受保護來序列化任何實體。

你可以有一個共同的問題與的Symfony2,即使您已設置的所有屬性,以保護:你必須重新生成你已經改變了這些實體的代理。爲此,只需清除緩存。對於開發環境

app/console cache:clear

它的工作原理,即使「它包含了許多異物,甚至外國實體的ArrayCollections」如你所說。

+0

謝謝,它幫助了很多。 – 2012-04-09 02:16:44

+0

如果可以的話,請回答我的問題的更新部分。 – 2012-04-09 12:02:36

+0

想一想:如果你存儲了所有的實體,你會在你的會話數據中存儲一個Big對象。對於你的發展環境來說,這不是問題。但是如果你有很多用戶,這是浪費資源。解決方案非常簡單:存儲對象的id並使用存儲庫的find()方法來檢索對象。最後,這是一回事。 – 2012-04-14 15:56:32

6

不推薦使用序列化實體,因爲您可以在Doctrine-documentation中看到。您應該實現Serializable-interface並手動序列化/反序列化實體數據。

+0

序列化我的實體將成爲問題。每次我需要它時,除了只存儲id並從數據庫中檢索對象之外,還有什麼更好的辦法? – 2012-02-21 21:06:57

+0

正如您從例外中看到的那樣,將其放入會話中時,它將被序列化,這就是導致錯誤的原因。但正如你所說,由於對象的複雜性,你可能應該去存儲這個id並且再次從數據庫中檢索對象。可能使用某種對象緩存也可以,但我不確定。 – dbrumann 2012-02-22 08:28:39

+1

謝謝,我只會存儲該ID。 – 2012-02-27 12:22:36

2

您可以通過overridding __sleep方法排除unnesseary字段:因爲它包含了許多異物,甚至外國實體的ArrayCollections

public function __sleep() { 

    // these are field names to be serialized, others will be excluded 
    // but note that you have to fill other field values by your own 
    return array('id', 'username', 'password', 'salt'); 
}