Symfony2将实体对象序列化为会话

时间:2012-02-21 20:42:36

标签: php session symfony entity

我想将我的一个实体对象保存到会话中,但是当我这样做时,我收到以下两个错误:

  

例外:   Symfony的\包\ FrameworkBundle \ DataCollector \ RequestDataCollector ::连载()   必须返回一个字符串或NULL

  

ErrorException:注意:serialize():“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);

我怎么能做对吗?

谢谢。

更新 有了Rowgm的帮助,我可以通过设置受保护而不是私有的属性来解决这个问题。我唯一的问题是在读取实体管理器不知道的会话中的实体之后,如果我将对象(从会话中)添加到另一个对象(它们之间存在OneToMany关系) ,它不会起作用。

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

这引发了一个错误,因为优惠券有一个对象属性,根据EntityManager不在数据库中(实际上它在数据库中,我从数据库中放入会话)。

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

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

但这似乎并不是最好的。我希望我的EntityManager能够感知存储在会话中的实体对象而不必每次都告诉它。 有什么想法吗?

3 个答案:

答案 0 :(得分:14)

您可以通过将所有属性和关系设置为私有受保护来序列化任何实体。

您可能会遇到与 symfony2 相关的常见问题,即使您已将所有属性设置为受保护:您必须重新生成已更改的实体的代理。为此,只需清除缓存即可。对于 dev环境

app/console cache:clear

即使“它包含许多异物,甚至包含外来实体的ArrayCollections”,它也能正常工作。

答案 1 :(得分:6)

建议不要序列化实体,如Doctrine-documentation中所示。您应该实现Serializable-interface并手动序列化/反序列化实体数据。

答案 2 :(得分:2)

您可以通过覆盖 __ sleep 方法来排除不必要的字段:

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');
}