PHPはMySQLでセッションを保存

25214 ワード

実装環境:
PHP 5.4.24

MySQL 5.6.19

OS X 10.9.4/Apache 2.2.26

一、コード
CREATE TABLE `session` (

  `skey` char(32) CHARACTER SET ascii NOT NULL,

  `data` text COLLATE utf8mb4_bin,

  `expire` int(11) NOT NULL,

  PRIMARY KEY (`skey`),

  KEY `index_session_expire` (`expire`) USING BTREE

) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
  1 <?php

  2 /*

  3  *         DNS、   、   ,              ,

  4  *          ,             global。

  5  */

  6 define('SESSION_DNS', 'mysql:host=localhost;dbname=db;charset=utf8mb4');

  7 define('SESSION_USR', 'usr');

  8 define('SESSION_PWD', 'pwd');

  9 define('SESSION_MAXLIFETIME', get_cfg_var('session.gc_maxlifetime'));

 10 

 11 //  PDO  

 12 //              

 13 function getConnection() {

 14     try {

 15         $conn = new PDO(SESSION_DNS, SESSION_USR, SESSION_PWD, array(

 16             PDO::ATTR_PERSISTENT => TRUE,

 17             PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,

 18             PDO::ATTR_EMULATE_PREPARES => FALSE

 19         ));

 20         return $conn;

 21     } catch (Exception $ex) {

 22 

 23     }

 24 }

 25 

 26 //    session open  

 27 function sessionMysqlOpen($savePath, $sessionName) {

 28     return TRUE;

 29 }

 30 

 31 //    session close  

 32 function sessionMysqlClose() {

 33     return TRUE;

 34 }

 35 /*

 36  *                    session,             。

 37  *    session   SQL         。              。

 38  *   ,                   。

 39  */

 40 /*

 41  * sessionMysqlRead()   ,    SELECT count(*)   sessionID    。

 42  *   MySQL     SELECT PDOStatement::rowCount()   ,

 43  *   ,            rowCount()    。

 44  */

 45 //    session read  

 46 //SQL      “expire > time()”  ,         session。

 47 function sessionMysqlRead($sessionId) {

 48     try {

 49         $dbh = getConnection();

 50         $time = time();

 51         

 52         $sql = 'SELECT count(*) AS `count` FROM session '

 53                 . 'WHERE skey = ? and expire > ?';

 54         $stmt = $dbh->prepare($sql);

 55         $stmt->execute(array($sessionId, $time));

 56         $data = $stmt->fetch(PDO::FETCH_ASSOC);

 57         if ($data['count'] = 0) {

 58             return '';

 59         }

 60         

 61         $sql = 'SELECT `data` FROM `session` '

 62                 . 'WHERE `skey` = ? and `expire` > ?';

 63         $stmt = $dbh->prepare($sql);

 64         $stmt->execute(array($sessionId, $time));

 65         $data = $stmt->fetch(PDO::FETCH_ASSOC);

 66         return $data['data'];

 67     } catch (Exception $e) {

 68         return '';

 69     }

 70 }

 71 

 72 //    session write  

 73 //expire            +session   ,      time()   session  。

 74 function sessionMysqlWrite($sessionId, $data) {

 75     try {

 76         $dbh = getConnection();

 77         $expire = time() + SESSION_MAXLIFETIME;

 78 

 79         $sql = 'INSERT INTO `session` (`skey`, `data`, `expire`) '

 80                 . 'values (?, ?, ?) '

 81                 . 'ON DUPLICATE KEY UPDATE data = ?, expire = ?';

 82         $stmt = $dbh->prepare($sql);

 83         $stmt->execute(array($sessionId, $data, $expire, $data, $expire));

 84     } catch (Exception $e) {

 85         echo $e->getMessage();

 86     }

 87 }

 88 

 89 //    session destroy  

 90 function sessionMysqlDestroy($sessionId) {

 91     try {

 92         $dbh = getConnection();

 93 

 94         $sql = 'DELETE FROM `session` where skey = ?';

 95         $stmt = $dbh->prepare($sql);

 96         $stmt->execute(array($sessionId));

 97         return TRUE;

 98     } catch (Exception $e) {

 99         return FALSE;

100     }

101 }

102 

103 //    session gc  

104 function sessionMysqlGc($lifetime) {

105     try {

106         $dbh = getConnection();

107 

108         $sql = 'DELETE FROM `session` WHERE expire < ?';

109         $stmt = $dbh->prepare($sql);

110         $stmt->execute(array(time()));

111         $dbh = NULL;

112         return TRUE;

113     } catch (Exception $e) {

114         return FALSE;

115     }

116 }

117 

118 //    session session id    

119 /*

120  *    session_start()  ,SID session_id()   ,

121  *    $_GET[session_name()] $_COOKIE[session_name()]    。

122  *         ,   session    ,    session  session id。

123  *   MySQL     uuid  session id       session id  。

124  */

125 function sessionMysqlId() {

126     if (filter_input(INPUT_GET, session_name()) == '' and

127             filter_input(INPUT_COOKIE, session_name()) == '') {

128         try {

129             $dbh = getConnection();

130             $stmt = $dbh->query('SELECT uuid() AS uuid');

131             $data = $stmt->fetch(PDO::FETCH_ASSOC);

132             $data = str_replace('-', '', $data['uuid']);

133             session_id($data);

134             return TRUE;

135         } catch (Exception $ex) {

136             return FALSE;

137         }

138         

139     }

140 }

141 

142 //session    ,   session_start()         。

143 function startSession() {

144     session_set_save_handler(

145             'sessionMysqlOpen',

146             'sessionMysqlClose',

147             'sessionMysqlRead',

148             'sessionMysqlWrite',

149             'sessionMysqlDestroy',

150             'sessionMysqlGc');

151     register_shutdown_function('session_write_close');

152     sessionMysqlId();

153     session_start();

154 }

二、紹介
  • MySQLを使用してセッションを保存するには、セッションid、セッションデータ、セッションライフ期間の3つの重要なデータを保存する必要があります.
  • セッションの使い方を考えると、InnoDBエンジンを使う必要はなく、MyISAMエンジンはより良い性能を得ることができます.環境が許可されている場合は、MEMORYエンジンを使用してみてください.
  • sessionデータの列を保存し、必要に応じてutf 8またはutf 8 mb 4文字セットを使用することができます.セッションidのカラムを保存する必要はありません.一般的にascii文字セットを使えばいいので、ストレージコストを節約できます.
  • sessionライフサイクルの列を保存し、工事の必要に応じて設計することができます.例えばdatetimeタイプ、timestampタイプ、intタイプです.datetime、intタイプの場合、セッション生成時間または有効期限を保存できます.
  • ユーザ名などの情報を保存するために、セッションテーブルのカラムを拡張し、読み取り、書き込み関数を変更して、関連するカラムをサポート(メンテナンス)する必要がある場合.
  • 現在のバージョンはセッションを通過する限りset_save_handlerはカスタムセッションメンテナンス関数を登録すればいいので、その前にsession_を使用する必要はありません.module_name('user')関数.
  • read関数がデータを取得して返されると、PHPは自動的に逆シーケンス化されます.一般的にはデータは変更しないでください.
  • PHPがwrite関数に渡すdateパラメータはシーケンス化されたセッションデータであり、そのまま保存すればよいので、一般的にはデータを変更しないでください.
  • このセグメントコードの論理に従って、PHP構成オプションはセッションのライフサイクルの設定についてもう有効ではありません.この値は自分で維持することができます.get_を通過する必要はありません.cfg_var取得.
  • sessionMysqlId()関数は,大ユーザ量,複数のWebサーバの場合の衝突を回避するためであり,一般的にPHPが自動的に生成するsession idはユーザの要求を満たすことができる.
  • がなくなった
  • 三、需要
    ユーザー数が非常に多く、複数のサーバでアプリケーションを提供する必要がある場合、MySQLストレージセッションを使用することは、セッションファイルを使用することに対して一定の優位性を有します.たとえば、ファイル共有による複雑さを回避したり、セッション・ファイル共有よりもパフォーマンスが向上したりするなど、ストレージ・オーバーヘッドを最小限に抑えることができます.全体的に、アクセスが急増している場合、データベースを使用してセッションを保存する問題が線形に増加している場合、セッションファイルを使用する問題はほとんど爆発的です.では、もっと率直な言い方に変えましょう.もしあなたのアプリケーションのユーザー量が少ないなら、PHPに自分でsessionを処理させておけばいいです.MySQLを考える必要はありません.
    四、参考
    1 http://cn2.php.net/manual/zh/function.session-set-save-handler.php
    
    2 http://cn2.php.net/manual/zh/session.idpassing.php
    
    3 http://cn2.php.net/manual/zh/pdo.connections.php
    
    4 http://cn2.php.net/manual/zh/pdo.prepared-statements.php
    
    5 http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#insert