欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

一个用mysql内存表来代替php session的类

程序员文章站 2022-05-30 13:55:21
...
  1. /**
  2. * session mysql内存表
  3. @Usage: use some other storage method(mysql or memcache) instead of php sessoin
  4. @author:lein
  5. @Version:1.2
  6. */
  7. session_start();
  8. if(!isset($_SESSION['test'])){
  9. $_SESSION['test']="123_lein_".date("Y-m-d H:i:s");
  10. }
  11. class session{
  12. //session data
  13. private $data;
  14. //engine,mysql or memcache
  15. private $engine;
  16. //php session expire time
  17. private $sessionexpiredTime;
  18. //current user's session cookie value
  19. private $sessionID;
  20. //session coolie name
  21. private $sessionCookieName;
  22. public function session($engineBase=NULL,$engineName='mysql',$storage_name='php_session'){
  23. try{
  24. $this->sessionexpiredTime = intval(ini_get("session.cache_expire"))*10;//默认是180分钟,太长了,改为了30分钟
  25. }catch(Exception $Exception){
  26. $this->sessionexpiredTime = 1200;
  27. }
  28. try{
  29. $this->sessionCookieName = ini_get("session.name");
  30. }catch(Exception $Exception){
  31. $this->sessionCookieName = 'PHPSESSID';
  32. }
  33. if(!isset($_COOKIE[$this->sessionCookieName])){
  34. @session_start();
  35. $this->sessionID=session_id();
  36. }else{
  37. $this->sessionID=$_COOKIE[$this->sessionCookieName];
  38. }
  39. $className = $engineName."SessionEngine";
  40. $this->engine = new $className(
  41. array(
  42. 'storage_name'=>$storage_name,//mysql table name or memcahce key which stores data;
  43. 'expire_time'=>$this->sessionexpiredTime,
  44. 'data_too_long_instead_value' => '{__DATA IS *$* TO LONG__}'
  45. ),
  46. $this->sessionID,
  47. &$engineBase
  48. );
  49. $this->init();
  50. $this->loadFromSession();
  51. $this->engine->refresh();
  52. $this->engine->cleanup();
  53. }
  54. private function init()
  55. {
  56. $this->data = $this->engine->get();
  57. if(empty($this->data)){
  58. @session_start();
  59. if(!empty($_SESSION)){
  60. $this->data = $_SESSION;
  61. $this->engine->create(false, $this->data);
  62. }
  63. else
  64. {
  65. $this->engine->create(false, "");
  66. }
  67. }
  68. }
  69. public function loadFromSession($flagStartSession = false){
  70. $flag=false;
  71. if($flagStartSession){
  72. @session_start();
  73. }
  74. if($_SESSION&&is_array($_SESSION)){
  75. foreach($_SESSION as $k=>$v){
  76. if(!isset($this->data[$k])){
  77. $this->data[$k] = $v;
  78. $flag=true;
  79. }
  80. }
  81. }
  82. if($flag){
  83. $this->engine->set(false, $this->data);
  84. }
  85. }
  86. private function __get($nm)
  87. {
  88. if (isset($this->data[$nm])) {
  89. $r = $this->data[$nm];
  90. return $r;
  91. }
  92. else
  93. {
  94. return NULL;
  95. }
  96. }
  97. private function __set($nm, $val)
  98. {
  99. $this->data[$nm] = $val;
  100. $this->engine->set(false, $this->data);
  101. }
  102. private function __isset($nm)
  103. {
  104. return isset($this->data[$nm]);
  105. }
  106. private function __unset($nm)
  107. {
  108. unset($this->data[$nm]);
  109. $this->engine->set(false, $this->data);
  110. }
  111. function __destruct(){
  112. $this->data = NULL;
  113. $this->engine->close();
  114. $this->engine = NULL;
  115. }
  116. }
  117. interface SessionEngine
  118. {
  119. /*
  120. * set varibles
  121. * @param $arr array,array(varible name=>varible value,...)
  122. */
  123. public function setVariable($arr);
  124. /*
  125. * get session value
  126. * @param $key string
  127. */
  128. public function get($key="");
  129. /*
  130. * set session value
  131. * @param $key string
  132. * @param $value string
  133. */
  134. public function set($key="",$value="");
  135. /*
  136. * set session value
  137. * @param $key string
  138. * @param $value string
  139. */
  140. public function create($key="",$value="");
  141. /*
  142. * update the session's invalid time
  143. * @param $key string
  144. */
  145. public function refresh($key="");
  146. /*
  147. * close mysql or memcache connection
  148. */
  149. public function close();
  150. /*
  151. * delete expired sessions
  152. */
  153. public function cleanup();
  154. }
  155. final class mysqlSessionEngine implements SessionEngine{
  156. private $id="";
  157. private $storage_name='php_session';
  158. private $storage_name_slow='php_session_slow';
  159. private $data_too_long_instead_value = '{__DATA IS ~ TO LONG__}';//if data is longer than $max_session_data_length and you are using mysql 4 or below,insert this value into memery table instead.
  160. private $expire_time=1200;
  161. private $max_session_data_length = 2048;
  162. private $conn;
  163. private $mysql_version;
  164. public function mysqlSessionEngine($arr=array(),$key="",&$_conn){
  165. $this->setVariable($arr);
  166. $this->id = $key;
  167. if(empty($this->id)||strlen($this->id)!=32){
  168. throw new Exception(__FILE__."->".__LINE__.": Session's cookie name can't be empty and it must have just 32 charactors!");
  169. }
  170. $this->conn = $_conn;
  171. if(!$this->conn||!is_resource($this->conn)){
  172. throw new Exception(__FILE__."->".__LINE__.": Need a mysql connection!");
  173. }
  174. $this->mysql_version = $this->getOne("select floor(version())");
  175. if($this->mysql_version $this->max_session_data_length = 255;
  176. }
  177. }
  178. public function setVariable($arr){
  179. if(!empty($arr)&&is_array($arr)){
  180. foreach($arr as $k=>$v){
  181. $this->$k = $v;
  182. if($k=='storage_name'){
  183. $this->storage_name_slow = $v.'_slow';
  184. }
  185. }
  186. }
  187. }
  188. public function get($key=""){
  189. if($key=="") $key = $this->id;
  190. $return = $this->getOne('select value from '.$this->storage_name.' where id="'.$key.'"');
  191. if($return==$this->data_too_long_instead_value)
  192. {
  193. $return = $this->getOne('select value from '.$this->storage_name_slow.' where id="'.$key.'"');
  194. }
  195. if(!$return)
  196. {
  197. $mysqlError = mysql_error($this->conn);
  198. if(strpos($mysqlError,"doesn't exist")!==false)
  199. {
  200. $this->initTable();
  201. }
  202. $return = array();
  203. }
  204. else
  205. {
  206. $return = unserialize($return);
  207. }
  208. return $return;
  209. }
  210. public function close(){
  211. @mysql_close($this->conn);
  212. }
  213. public function cleanup(){
  214. if($this->mysql_version>4){
  215. $sql = 'delete from '.$this->storage_name.' where date_add(`time`,INTERVAL '.$this->expire_time.' SECOND) }else{
  216. $sql = 'delete from '.$this->storage_name_slow.' where `time`+'.$this->expire_time.' if($_SESSION['username']=="leinchu"){
  217. echo $sql;
  218. }
  219. $this->execute($sql);
  220. $sql = 'delete from '.$this->storage_name.' where `time`+'.$this->expire_time.' if($_SESSION['username']=="leinchu"){
  221. echo $sql;
  222. }
  223. }
  224. $this->execute($sql);
  225. }
  226. public function refresh($key=""){
  227. if($this->mysql_version>4){
  228. $sql = 'update '.$this->storage_name.' set `time`=CURRENT_TIMESTAMP() where id="'.$key.'"';
  229. }else{
  230. $sql = 'update '.$this->storage_name.' set `time`=unix_timestamp() where id="'.$key.'"';
  231. }
  232. $return = $this->execute($sql);
  233. if(!$return){
  234. $this->initTable();
  235. $return = $this->execute($sql,true);
  236. }
  237. return $return;
  238. }
  239. public function create($key="",$value=""){
  240. if($key=="") $key = $this->id;
  241. if($value != "") $value = mysql_real_escape_string(serialize($value),$this->conn);
  242. if(strlen($value)>$this->max_session_data_length)
  243. {
  244. if($this->mysql_version>4){
  245. throw new Exception(__FILE__."->".__LINE__.": Session data is long than max allow length(".$this->max_session_data_length.")!");
  246. }
  247. }
  248. if($this->mysql_version>4){
  249. $sql = 'replace into '.$this->storage_name.' set value=/''.$value.'/',id="'.$key.'",`time`=CURRENT_TIMESTAMP()';
  250. }else{
  251. $sql = 'replace into '.$this->storage_name.' set value=/''.$value.'/',id="'.$key.'",`time`=unix_timestamp()';
  252. }
  253. $return = $this->execute($sql);
  254. if(!$return){
  255. $this->initTable();
  256. $return = $this->execute($sql,true);
  257. }
  258. return $return;
  259. }
  260. public function set($key="",$value=""){
  261. if($key=="") $key = $this->id;
  262. if($value != "") $value = mysql_real_escape_string(serialize($value),$this->conn);
  263. $sql = 'update '.$this->storage_name.' set value=/''.$value.'/' where id="'.$key.'"';
  264. if(strlen($value)>$this->max_session_data_length)
  265. {
  266. if($this->mysql_version>4){
  267. throw new Exception(__FILE__."->".__LINE__.": Session data is long than max allow length(".$this->max_session_data_length.")!");
  268. }
  269. $sql = 'replace into '.$this->storage_name_slow.' set value=/''.$value.'/',id="'.$key.'",`time`=unix_timestamp()';
  270. $this->execute($sql,true);
  271. $sql = 'update '.$this->storage_name.' set value=/''.$this->data_too_long_instead_value.'/' where id="'.$key.'"';
  272. }
  273. $return = $this->execute($sql);
  274. if(!$return){
  275. $this->initTable();
  276. $return = $this->execute($sql,true);
  277. }
  278. return $return;
  279. }
  280. private function initTable(){
  281. if($this->mysql_version>4){
  282. $sql = "
  283. CREATE TABLE if not exists `".$this->storage_name."` (
  284. `id` char(32) NOT NULL default 'ERR',
  285. `value` VARBINARY(".$this->max_session_data_length.") NULL,
  286. `time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  287. PRIMARY KEY (`id`),
  288. KEY `time` (`time`)
  289. ) ENGINE=MEMORY;
  290. ";
  291. }else{
  292. $sqlSlow = "
  293. CREATE TABLE if not exists `".$this->storage_name."_slow` (
  294. `id` char(32) NOT NULL default 'ERR',
  295. `value` text NULL,
  296. `time` int(10) not null default '0',
  297. PRIMARY KEY (`id`),
  298. KEY `time` (`time`)
  299. ) ENGINE=MyISAM;
  300. ";
  301. $this->execute($sqlSlow,true);
  302. $sql = "
  303. CREATE TABLE if not exists `".$this->storage_name."` (
  304. `id` char(32) NOT NULL default 'ERR',
  305. `value` VARCHAR(255) NULL,
  306. `time` int(10) not null default '0',
  307. PRIMARY KEY (`id`),
  308. KEY `time` (`time`)
  309. ) ENGINE=MEMORY;
  310. ";
  311. }
  312. return $this->execute($sql,true);
  313. }
  314. private function execute($sql,$die=false)
  315. {
  316. if($die)
  317. {
  318. mysql_query($sql,$this->conn) or die("exe Sql error:
    ".mysql_error()."
    ".$sql."
    ");
  319. }
  320. else
  321. {
  322. mysql_query($sql,$this->conn);
  323. if(mysql_error()){
  324. return false;
  325. }else{
  326. return true;
  327. }
  328. }
  329. }
  330. private function getOne($sql,$die=false){
  331. $rs = $this->query($sql,$die);
  332. if($rs && ($one = mysql_fetch_row($rs)) ){
  333. return $one[0];
  334. }else{
  335. return false;
  336. }
  337. }
  338. private function query($sql,$die=false){
  339. if($die)
  340. $rs = mysql_query($sql,$this->conn) or die("query Sql error:
    ".mysql_error()."
    ".$sql."
    ");
  341. else
  342. $rs = mysql_query($sql,$this->conn);
  343. return $rs;
  344. }
  345. }
  346. $lnk = mysql_connect('localhost', 'root', '123456')
  347. or die ('Not connected : ' . mysql_error());
  348. // make foo the current db
  349. mysql_select_db('test', $lnk) or die ('Can/'t use foo : ' . mysql_error());
  350. $S = new session($lnk);
  351. if(!$S->last){
  352. $S->last = time();
  353. }
  354. echo "First visit at ".$S->last."
    ";
  355. if(!$S->lastv){
  356. $S->lastv = 0;
  357. }
  358. $S->lastv++;
  359. echo "lastv=".$S->lastv."
    ";
  360. echo "test=".$S->test."
    ";
  361. if(isset($_GET['max'])){
  362. $S->boom = str_repeat("OK",255);
  363. }
  364. if(isset($_GET['boom'])){
  365. $S->boom = $_GET['boom'];
  366. }
  367. echo "boom=".$S->boom."
    ";
  368. ?>
复制代码