PHP:将“对象”存储在$ _SESSION中
我只是想到,我实际上可以将对象存储在$ _SESSION中 ,我发现它非常酷,因为当我跳到另一个页面时,我仍然有我的对象。 现在,在我开始使用这种方法之前,我想知道这是否真的是一个好主意,或者是否有潜在的陷阱 。
我知道,如果我有一个单一的入口点,我不需要这样做,但是我还没有,所以我没有一个单一的入口点,我真的想保留我的对象,因为我不'不会那样失去我的状态。 (现在我也读了,我应该编程无国籍的网站,但我不明白这个概念呢。)
所以简而言之 :在会话中存储对象是否可行,是否有任何问题?
编辑:
临时摘要 :现在我明白,即使重新查询数据库,重新创build对象也可能更好 。
进一步的答案可能会详细阐述这一点!
我知道这个话题已经很久了,但是这个问题还在继续,并没有得到我的满意:
无论是将对象保存在$ _SESSION中,还是根据隐藏的表单字段中的数据重新构build整个布料,或者每次都从数据库重新查询它们,则您正在使用状态。 HTTP是无状态的(或多或less,但看到GET与PUT),但几乎所有人都在关心做一个Web应用程序需要状态保持在某个地方。 如果把国家推到一个理论上的胜利就是错误的。 国家是国家。 如果你使用状态,你失去了无国籍获得的各种技术优势。 除非事先知道自己应该失眠,否则这不是失眠的结果。
汉克·盖伊(Hank Gay)提出的“双重打击”(double whammy)的论点所带来的祝福使我特别失望。 OP是否构build了一个分布式,负载均衡的电子商务系统? 我的猜测是不。 我会进一步假设序列化他的$用户类,或其他任何,不会削弱他的服务器无法修复。 我的build议是:使用对您的应用程序有意义的技术。 $ _SESSION中的对象是很好的,但要注意常识。 如果你的应用程序突然变成了在交通服务中与亚马逊相媲美的东西,你将需要重新适应。 那就是生活。
只要在进行session_start()调用的时候就可以了,类声明/定义已经被PHP遇到了,或者可以被已经安装的自动加载器find。 否则它将无法从会话存储中反序列化对象。
HTTP是一个无状态的协议。 会话将状态焊接到HTTP上。 作为一个经验法则,避免使用会话状态。
更新:在HTTP级别没有会话的概念; 服务器通过为客户端提供一个唯一的ID并告诉客户端在每个请求中重新提交来提供这个服务。 然后服务器使用该ID作为一个关键字进入Session对象的哈希表。 每当服务器收到请求时,都会根据客户端随请求提交的ID查找会话对象散列表中的会话信息。 所有这些额外的工作对可伸缩性来说都是双重打击(HTTP是无状态的一个重要原因)。
- Whammy One:它减less了单个服务器可以完成的工作。
- Whammy Two:这使得扩展更加困难,因为现在你不能将请求路由到任何旧的服务器 – 它们并不都具有相同的会话。 您可以将具有给定会话ID的所有请求连接到同一台服务器。 这并不容易,而且是单点故障(不是整个系统,而是大部分用户)。 或者,您可以跨群集中的所有服务器共享会话存储,但是现在您拥有更多的复杂性:networking连接内存,独立会话服务器等。
考虑到这一点,您在会议中提供的信息越多,对性能的影响就越大(如温科指出的那样)。 就像温科指出的那样,如果你的对象不是可序列化的,那么这个会话就会不正常。 所以,作为一个经验法则,避免在会议中超出绝对的必要。
@Vinko你通常可以通过在你发回的响应中embedded你正在跟踪的数据并让客户端重新提交它,例如,通过隐藏的input发送数据来解决服务器存储状态。 如果你真的需要服务器端的状态跟踪,它应该可能在你的支持数据存储。
(Vinko补充道:PHP可以使用数据库来存储会话信息,并且让客户端每次重新提交数据可能会解决潜在的可伸缩性问题,但是会打开一大堆的安全问题,您必须注意到现在客户端在控制所有你的状态)
- 无法序列化的对象(或包含非序列化成员的对象)不会像您所期望的那样从$ _SESSION中出来
- 巨大的会话给服务器带来了负担(每次对串口进行串行化和反序列化都是昂贵的)
除此之外,我没有看到任何问题。
根据我的经验,通常不值得这样做比任何具有某些属性的StdClass更复杂。 反序列化的成本一直不止是从给定会话存储的标识符的数据库重新创build。 这似乎很酷,但(一如既往),分析是关键。
我build议不要使用状态,除非你绝对需要它。 如果你可以重build对象,而不使用会话做到这一点。 在您的Web应用程序中有状态会使应用程序的构build更加复杂,对于每个请求,您都必须查看用户所处的状态。当然,有些时候您无法避免使用会话(例如:用户必须在会话期间保持login状态networking应用程序)。 最后,我build议保持会话对象尽可能小,因为它会影响性能以序列化和反序列化大型对象。
你必须记住,资源types(如数据库连接或文件指针)不会在页面加载之间持续,你需要不可见地重新创build这些。
还要考虑会话的大小,取决于它的存储方式,可能会有大小限制或延迟问题。
当升级软件库时,我们也会提出 – 我们升级了软件,而旧版本在V1软件的类名称的对话中,新软件在尝试构build会话中的对象时崩溃了,因为V2软件不再使用这些相同的类,它找不到它们。 我们不得不放入一些修复代码来检测会话对象,如果发现会删除会话,重新加载页面。 最初的最大痛苦就是在第一次报告时重新创build这个bug(所有这些都很熟悉,“对我来说,这很有用”:),因为它只影响那些新旧系统进出的人 – 但是,因为我们所有的用户在他们的会话中肯定会有旧的会话variables,并且可能已经崩溃了,所以我们在发布之前就已经find了。
无论如何,正如你在修正案中所build议的那样,我也觉得重build对象最好。 所以也许只是存储ID,然后在每个请求从数据库中拉对象,是更好/更安全。