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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9384836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 06:41:40  来源:igfitidea点击:

Symfony2 serialize entity object to session

phpsessionsymfonyentity

提问by David Frank

I want to save one of my entity objects into the session, but as I'm doing so, I'm getting the following two errors:

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

Exception: Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::serialize() must return a string or NULL

例外:Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::serialize() 必须返回一个字符串或 NULL

and

ErrorException: Notice: serialize(): "id" returned as member variable from __sleep() but does not exist in /var/www/clients/client71/web256/web/_dev_fd/kkupon/vendor/symfony/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php line 29

ErrorException:注意:serialize():从 __sleep() 作为成员变量返回的“id”但不存在于 /var/www/clients/client71/web256/web/_dev_fd/kkupon/vendor/symfony/src/Symfony/Component /HttpKernel/DataCollector/DataCollector.php 第 29 行

My code goes like this:

我的代码是这样的:

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

How could I get it right?

我怎么做对?

Thank you.

谢谢你。

UPDATEWith Rowgm's help I could fix this problem by setting properties protected instead of private. The only problem I have is after readingthe entity from the session the EntityManager does not know about it, and if I add the object(from the session) to another object(there is OneToMany relationship between them), it won't work.

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

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

This raises an error, because coupon has an object property which according to the EntityManager is not in the database(actually it is in the DB, I put to the session from the DB).

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

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

One solution can be: $offer = $this->em->merge($offer);

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

But this doesnt seem to be the best one. I'd like my EntityManager to perceive entity objects stored in session without telling it each time. Any idea?

但这似乎不是最好的。我希望我的 EntityManager 能够感知存储在会话中的实体对象,而无需每次都告诉它。任何的想法?

回答by Rowinson Gallego

You can serialize any entity by setting all their properties and relationships from privateto protected.

您可以通过将其所有属性和关系从private 设置protected来序列化任何实体。

You could have a common issue with symfony2, even if you have set all properties to protected: You have to re-generate the proxies of those entities you have changed. To do so, simply clear the cache. For dev enviroment:

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

app/console cache:clear

app/console cache:clear

It works even if "it contains many foreign objects and even ArrayCollections of foreign entities" as you said.

即使如您所说的“它包含许多外来对象甚至外来实体的 ArrayCollections”,它也能工作。

回答by dbrumann

Serializing entities is not recommended, as you can see in the Doctrine-documentation. You should implement the Serializable-interfaceand serialize/deserialize the entity-data manually.

不推荐序列化实体,正如您在Doctrine-documentation 中看到的那样。您应该实现Serializable-interface并手动序列化/反序列化实体数据。

回答by pleerock

You can exclude unnesseary fields by overridding __sleepmethod:

您可以通过覆盖__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');
}