0

0

关于PHP的Session处理的问题

php中文网

php中文网

发布时间:2016-06-06 19:52:22

|

1518人浏览过

|

来源于php中文网

原创

问题源自于深空博客的这篇文章《由会话重定向看到的对象销毁问题》,嗯,我以为这种问题早有人处理过了,因为2年前我就解决了此问题。解决办法已经发在phpchina.com的原创区:《关于PHP的Session处理的问题》。不过我在自己的博客上也发表同样的一篇帖子,留

问题源自于深空博客的这篇文章《由会话重定向看到的对象销毁问题》,嗯,我以为这种问题早有人处理过了,因为2年前我就解决了此问题。解决办法已经发在phpchina.com的原创区:《关于php的session处理的问题》。不过我在自己的博客上也发表同样的一篇帖子,留作备份。

 

在专家板块看到有人提出对Session处理机制的问题,原文《由会话重定向看到的对象销毁问题》。由于本人没有在专家板块发帖的资格,所以在这里发。

大概在08年年头我开始放弃Ruby on Rails转移到PHP开发,并以RoR的一些精神开发基于PHP的MVC框架,08年年底的时候,曾在phpchina这里发过一帖《自写MVC框架 Agi PHPMVC(核心)》,可以这么说,从我接触PHP以来一直是以自写的MVC框架在进行开发。目前该框架取名Agi on Rails,已经进入正式版的1.2版,下一个release版本将会考虑开源。该框架已经成功稳定的运行在多个Server Env(Windows、Linux,IIS、Apache、Lighttpd、Nginx),开发过超过20个项目,承受过一天超过1200万PV的洗礼(预计并发峰值在200左右)。为何加这一个插曲,是为了强调,我是坚持将数据操作写在Model层的,而Session处理的逻辑,是被设计成一个 Model,而随着众多Model被Controler和View层调用。而开发者,是可以针对Session这个模块进行后期的高级的逻辑封装的。

废话就不多说了,解决方案如下: 

立即学习PHP免费学习笔记(深入)”;

 

<p><span> 1</span> <span>//</span><span> 数据库连接的抽象层</span><span><br></span><span> 2</span> <span> </span><span>abstract</span><span>class</span><span> DB_Connector {<br></span><span> 3</span> <span>    <br></span><span> 4</span> <span>protected</span><span>static</span><span><br></span><span> 5</span> <span>$_register</span><span>=</span><span>array</span><span>();<br></span><span> 6</span> <span><br></span><span> 7</span> <span>static</span><span>public</span><span>function</span><span> connect(</span><span>$anyKey</span><span>) {<br></span><span> 8</span> <span>//</span><span> 假设传入的$anyKey指定要使用MySQL进行连接<br></span><span> 9</span> <span>        // 这中间的一些判断这里就忽略了</span><span><br></span><span>10</span> <span> </span><span>if</span><span> (</span><span>!</span><span>isset</span><span>(self</span><span>::</span><span>$_register</span><span>[</span><span>$anyKey</span><span>])) {<br></span><span>11</span> <span>            self</span><span>::</span><span>$_register</span><span>[</span><span>$anyKey</span><span>] </span><span>=</span><span>new</span><span> DB_Connector_MySQL();<br></span><span>12</span> <span>        }<br></span><span>13</span> <span>return</span><span> self</span><span>::</span><span>$_register</span><span>[</span><span>$anyKey</span><span>];<br></span><span>14</span> <span>    }<br></span><span>15</span> <span><br></span><span>16</span> <span>static</span><span>public</span><span>function</span><span> disconnect(</span><span>$anyKey</span><span>) {<br></span><span>17</span> <span>        self</span><span>::</span><span>connect(</span><span>$anyKey</span><span>)</span><span>-></span><span>disconnect();<br></span><span>18</span> <span>    }<br></span><span>19</span> <span><br></span><span>20</span> <span>static</span><span>public</span><span>function</span><span> handleDisconnect(</span><span>$anyKey</span><span>) {<br></span><span>21</span> <span>        self</span><span>::</span><span>connect(</span><span>$anyKey</span><span>)</span><span>-></span><span>handleDisconnect();<br></span><span>22</span> <span>    }<br></span><span>23</span> <span>}<br></span><span>24</span> <span><br></span><span>25</span> <span> </span><span>//</span><span> 数据库连接的驱动层</span><span><br></span><span>26</span> <span> </span><span>class</span><span> DB_Connector_MySQL {<br></span><span>27</span> <span>    <br></span><span>28</span> <span>protected</span><span><br></span><span>29</span> <span>$_connector</span><span>=</span><span>null</span><span>,</span><span><br></span><span>30</span> <span>$_isHandleDisconnect</span><span>=</span><span>false</span><span>;<br></span><span>31</span> <span><br></span><span>32</span> <span>public</span><span>function</span><span> __construct() {<br></span><span>33</span> <span>//</span><span> 执行具体的连接</span><span><br></span><span>34</span> <span> </span><span>$this</span><span>-></span><span>_connector </span><span>=</span><span>new</span><span> MySQLDriver();<br></span><span>35</span> <span>    }<br></span><span>36</span> <span>    <br></span><span>37</span> <span>public</span><span>function</span><span> __destruct() {<br></span><span>38</span> <span>if</span><span> (</span><span>!</span><span>$this</span><span>-></span><span>_isHandleDisconnect)<br></span><span>39</span> <span>$this</span><span>-></span><span>disconnect();<br></span><span>40</span> <span>    }<br></span><span>41</span> <span><br></span><span>42</span> <span>public</span><span>function</span><span> disconnect() {<br></span><span>43</span> <span>$this</span><span>-></span><span>_connector </span><span>=</span><span>null</span><span>;<br></span><span>44</span> <span>    }<br></span><span>45</span> <span><br></span><span>46</span> <span>public</span><span>function</span><span> handleDisconnect() {<br></span><span>47</span> <span>$this</span><span>-></span><span>_isHandleDisconnect </span><span>=</span><span>true</span><span>;<br></span><span>48</span> <span>    }<br></span><span>49</span> <span>}<br></span><span>50</span> <span><br></span><span>51</span> <span> </span><span>//</span><span> Session的实现层<br></span><span>52</span> <span>// Any_ActiveRecord是Model的抽象层,这里就不实现了</span><span><br></span><span>53</span> <span> </span><span>class</span><span> Session </span><span>extends</span><span> Any_ActiveRecord {<br></span><span>54</span> <span>    <br></span><span>55</span> <span>protected</span><span>static</span><span><br></span><span>56</span> <span>$_connectorKey</span><span>=</span><span>'</span><span>Any</span><span>'</span><span>;<br></span><span>57</span> <span><br></span><span>58</span> <span>//</span><span> 标准实现</span><span><br></span><span>59</span> <span>static</span><span>public</span><span>function</span><span> open() {<br></span><span>60</span> <span>//</span><span> 一旦将Session处理转移给DB层面去控制<br></span><span>61</span> <span>        // 就意味着数据库连接的释放,也必须转交给这个Session模块来处理</span><span><br></span><span>62</span> <span>        DB_Connector</span><span>::</span><span>handleDisconnect(self</span><span>::</span><span>$_connectorKey</span><span>);<br></span><span>63</span> <span>//</span><span> 其他启动配置,包括Session GC清理的基数等等</span><span><br></span><span>64</span> <span>    }<br></span><span>65</span> <span>    <br></span><span>66</span> <span>//</span><span> 标准实现<br></span><span>67</span> <span>    // </span><span><br></span><span>68</span> <span>static</span><span>public</span><span>function</span><span> pick(</span><span>$sId</span><span>) {<br></span><span>69</span> <span>        <br></span><span>70</span> <span>    }<br></span><span>71</span> <span><br></span><span>72</span> <span>//</span><span> 标准实现</span><span><br></span><span>73</span> <span>static</span><span>public</span><span>function</span><span> dump(</span><span>$sId</span><span>,</span><span>$val</span><span>) {<br></span><span>74</span> <span>        <br></span><span>75</span> <span>    }<br></span><span>76</span> <span><br></span><span>77</span> <span>//</span><span> 标准实现</span><span><br></span><span>78</span> <span>static</span><span>public</span><span>function</span><span> destroy(</span><span>$sId</span><span>) {<br></span><span>79</span> <span>        <br></span><span>80</span> <span>    }<br></span><span>81</span> <span><br></span><span>82</span> <span>//</span><span> 标准实现</span><span><br></span><span>83</span> <span>static</span><span>public</span><span>function</span><span> gc() {<br></span><span>84</span> <span>        <br></span><span>85</span> <span>    }<br></span><span>86</span> <span><br></span><span>87</span> <span>//</span><span> 标准实现</span><span><br></span><span>88</span> <span>static</span><span>public</span><span>function</span><span> close() {<br></span><span>89</span> <span>//</span><span> 一切OK,再由Session Close的时候,释放数据库连接</span><span><br></span><span>90</span> <span>        DB_Connector</span><span>::</span><span>disconnect(self</span><span>::</span><span>$_connectorKey</span><span>);<br></span><span>91</span> <span>    }<br></span><span>92</span> <span>}</span></p>

至此,第一个问题解决了,就是关于数据库连接的释放问题。但是这里存在第二个问题(假如你在使用的框架,取出的Session是一个数组,或者你直接就取出的是一个数组,可以忽略第二个问题),就是按照常理,一个Session经由Model取出,理应被是一个Session的实例,然后,由于PHP本身的运行机制的问题,变量的释放,往往早于Session的注销。这时就要发挥出OO的本色了:

 

根据上述的Session类,我们进行一点点改造:

php商城系统
php商城系统

PHP商城系统是国内功能优秀的网上商城系统,同时也是一个商业的PHP开发框架,有多套免费模版,强大的后台管理功能,专业的网上商城系统解决方案,快速建设网上购物商城、数码商城、手机商城、办公用品商城等网站。 php商城系统v3.0 rc6升级 1、主要修复用户使用中出现的js未加载完报错问题,后台整改、以及后台栏目的全新部署、更利于用户体验。 2、扩展出,更多系统内部的功能,以便用户能够迅速找到需

下载

 

<p><span> 1</span> <span>//</span><span> Session的实现层<br></span><span> 2</span> <span>// Any_ActiveRecord是Model的抽象层,这里就不实现了</span><span><br></span><span> 3</span> <span>class</span><span> Session </span><span>extends</span><span> Any_ActiveRecord {<br></span><span> 4</span> <span>    <br></span><span> 5</span> <span>protected</span><span>static</span><span><br></span><span> 6</span> <span>$_connectorKey</span><span>=</span><span>'</span><span>Any</span><span>'</span><span>,</span><span><br></span><span> 7</span> <span>$_currSess</span><span>=</span><span>null</span><span>;<br></span><span> 8</span> <span><br></span><span> 9</span> <span>//</span><span> 标准实现</span><span><br></span><span>10</span> <span>static</span><span>public</span><span>function</span><span> open() {<br></span><span>11</span> <span>//</span><span> 一旦将Session处理转移给DB层面去控制<br></span><span>12</span> <span>        // 就意味着数据库连接的释放,也必须转交给这个Session模块来处理</span><span><br></span><span>13</span> <span>        DB_Connector</span><span>::</span><span>handleDisconnect(self</span><span>::</span><span>$_connectorKey</span><span>);<br></span><span>14</span> <span>//</span><span> 其他启动配置,包括Session GC清理的基数等等</span><span><br></span><span>15</span> <span>    }<br></span><span>16</span> <span>    <br></span><span>17</span> <span>//</span><span> 标准实现<br></span><span>18</span> <span>    // 拿出Session</span><span><br></span><span>19</span> <span>static</span><span>public</span><span>function</span><span> pick(</span><span>$sId</span><span>) {<br></span><span>20</span> <span>        self</span><span>::</span><span>$_currSess</span><span>=</span><span> self</span><span>::</span><span>find_by_sess_id(</span><span>$sId</span><span>);<br></span><span>21</span> <span>if</span><span> (</span><span>!</span><span>self</span><span>::</span><span>$_currSess</span><span>-></span><span>isEmpty())<br></span><span>22</span> <span>return</span><span> self</span><span>::</span><span>$_currSess</span><span>-></span><span>value;<br></span><span>23</span> <span>return</span><span>false</span><span>;<br></span><span>24</span> <span>    }<br></span><span>25</span> <span><br></span><span>26</span> <span>//</span><span> 标准实现</span><span><br></span><span>27</span> <span>static</span><span>public</span><span>function</span><span> dump(</span><span>$sId</span><span>,</span><span>$val</span><span>) {<br></span><span>28</span> <span>//</span><span> 新访客</span><span><br></span><span>29</span> <span>if</span><span> (self</span><span>::</span><span>$_currSess</span><span>-></span><span>isEmpty())<br></span><span>30</span> <span>            self</span><span>::</span><span>$_currSess</span><span>-></span><span>sess_id </span><span>==</span><span>$sId</span><span>;<br></span><span>31</span> <span>        self</span><span>::</span><span>$_currSess</span><span>-></span><span>value </span><span>=</span><span>$val</span><span>;<br></span><span>32</span> <span>        self</span><span>::</span><span>$_currSess</span><span>-></span><span>save();<br></span><span>33</span> <span>    }<br></span><span>34</span> <span><br></span><span>35</span> <span>//</span><span> 标准实现</span><span><br></span><span>36</span> <span>static</span><span>public</span><span>function</span><span> destroy(</span><span>$sId</span><span>) {<br></span><span>37</span> <span>        <br></span><span>38</span> <span>    }<br></span><span>39</span> <span><br></span><span>40</span> <span>//</span><span> 标准实现</span><span><br></span><span>41</span> <span>static</span><span>public</span><span>function</span><span> gc() {<br></span><span>42</span> <span>        <br></span><span>43</span> <span>    }<br></span><span>44</span> <span><br></span><span>45</span> <span>//</span><span> 标准实现</span><span><br></span><span>46</span> <span>static</span><span>public</span><span>function</span><span> close() {<br></span><span>47</span> <span>//</span><span> 一切OK,再由Session Close的时候,释放数据库连接</span><span><br></span><span>48</span> <span>        DB_Connector</span><span>::</span><span>disconnect(self</span><span>::</span><span>$_connectorKey</span><span>);<br></span><span>49</span> <span>        self</span><span>::</span><span>$_currSess</span><span>=</span><span>null</span><span>;<br></span><span>50</span> <span>    }<br></span><span>51</span> <span>}</span></p>

好了,大功告成!原理就不多说了,多做点测试吧。

 

将Session写成Model的好处是,可以有针对性的进行单元测试。也许有用户会担心,你把Session放在数据库层,能承受得多大的并发量呢?

OK,我可以给出一些实际数据,一个投票的程序,PHP和MySQL跑在同一台服务器(Server系统是Ubuntu Server以Lighttpd,已经通过压力测试优化过fastcgi线程数字)上,3天收集有效投票记录总数900万+(注意,有效投票是指限制ip的,每一票都要检查ip和该ip上一次投票的时间),Session使用Model操作,以MyISAM引擎存放在MySQL的表中,Session主键已经刷到8位数。最高峰一天PV 1200万。

 

另:我发现cnblogs的源代码极其以及十分之丑陋,无法让人家复制代码,提供附件下载。

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

6

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

8

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

14

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

17

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

2

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

130

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

8

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

208

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 6.3万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 9.9万人学习

Django 教程
Django 教程

共28课时 | 4.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号