Maison >développement back-end >tutoriel php >一个用mysql内存表来代替php session的类

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

WBOY
WBOYoriginal
2016-07-25 08:57:23833parcourir
  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. ?>
复制代码


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn