来自Symfony 2食谱:Understanding serialize and how a User is Saved in the Session:
用户登录后,整个用户对象将被序列化 会议。在下一个请求中,反序列化User对象。 然后,id属性的值用于重新查询新用户 来自数据库的对象。
和
...实际上,这意味着用户对象从中重新加载 每个请求上的数据库使用序列化对象的id。
为什么Symfony必须在每次请求时从数据库中获取User对象?
在什么情况下,存储在会话数据中的序列化User对象与从数据库中提取的User对象不匹配?当然,Symfony知道用户对象何时发生变化,并且只能在发生这种情况时更新会话数据?
我认为这是有充分理由的,因为在每次请求时不必要地查询数据库会很浪费。
答案 0 :(得分:13)
免责声明:我不具体了解Symfony,因此这是根据一般的PHP知识和一些假设编写的。
PHP会话通常不能从外部操作 - 它们只是文件或内存存储中的序列化数据块。改变一种方法的唯一方法是对其进行反序列化,进行更改并对整个事物进行重新序列化 - 这通常仅在您进入该会话时才会完成。
因此,如果用户的详细信息在登录会话之外更改,则序列化blob将保持过期。这将是一个特殊问题,例如,如果管理员撤销了用户的访问权限。
诸如memcached之类的缓存可能存储每个用户的详细信息,并在编辑时显式刷新/更改,但这将被视为数据库提取的一部分(memcached层充当对数据库数据的更快访问),而不是会话处理。
在评论中询问 haltabush :如果每次请求都提取了用户,为什么要将其序列化呢?
答案是需要在会话中存储足够的信息以识别登录的用户,并在下一页加载时获取其完整详细信息。这可以像存储用户ID一样简单,但是通过使用Serializable
接口,Symfony可以将其留给特定的实现来决定哪些字段应该保存到会话中,哪些字段应该重新在被反序列化时获取。
它还为实现保留了打开选项,以将用户的所有细节保存到会话中,并在更轻松的基础上“刷新”,例如,经过一段时间或一定数量的请求后,如this related question所述。
答案 1 :(得分:4)
在什么情况下,存储在会话数据中的序列化User对象与从数据库中提取的User对象不匹配?
例如,当管理员更改用户拥有的权限/权限时 - 这通常是您希望立即生效的 ,而不仅仅是当用户注销然后再次进入时
当然,Symfony知道用户对象何时发生变化,并且只能在发生这种情况时更新会话数据?
当该更改与用户会话没有任何关联时,就不会出现这种情况。