PHP利用MySQL保存session的实现思路及示例代码,mysqlsession
PHP利用MySQL保存session的实现思路及示例代码,mysqlsession
实现环境:
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;
<?php /* * 连接数据库所需的DNS、用户名、密码等,一般情况不会在代码中进行更改, * 所以使用常量的形式,可以避免在函数中引用而需要global。 */ define('SESSION_DNS', 'mysql:host=localhost;dbname=db;charset=utf8mb4'); define('SESSION_USR', 'usr'); define('SESSION_PWD', 'pwd'); define('SESSION_MAXLIFETIME', get_cfg_var('session.gc_maxlifetime')); //创建PDO连接 //持久化连接可以提供更好的效率 function getConnection() { try { $conn = new PDO(SESSION_DNS, SESSION_USR, SESSION_PWD, array( PDO::ATTR_PERSISTENT => TRUE, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => FALSE )); return $conn; } catch (Exception $ex) { } } //自定义的session的open函数 function sessionMysqlOpen($savePath, $sessionName) { return TRUE; } //自定义的session的close函数 function sessionMysqlClose() { return TRUE; } /* * 由于一般不会把用户提交的数据直接保存到session,所以普通情况不存在注入问题。 * 且处理session数据的SQL语句也不会多次使用。因此预处理功能的效益无法体现。 * 所以,实际工程中可以不必教条的使用预处理功能。 */ /* * sessionMysqlRead()函数中,首先通过SELECT count(*)来判断sessionID是否存在。 * 由于MySQL数据库提供SELECT对PDOStatement::rowCount()的支持, * 因此,实际的工程中可以直接使用rowCount()进行判断。 */ //自定义的session的read函数 //SQL语句中增加了“expire > time()”判断,用以避免读取过期的session。 function sessionMysqlRead($sessionId) { try { $dbh = getConnection(); $time = time(); $sql = 'SELECT count(*) AS `count` FROM session ' . 'WHERE skey = ? and expire > ?'; $stmt = $dbh->prepare($sql); $stmt->execute(array($sessionId, $time)); $data = $stmt->fetch(PDO::FETCH_ASSOC)['count']; if ($data = 0) { return ''; } $sql = 'SELECT `data` FROM `session` ' . 'WHERE `skey` = ? and `expire` > ?'; $stmt = $dbh->prepare($sql); $stmt->execute(array($sessionId, $time)); $data = $stmt->fetch(PDO::FETCH_ASSOC)['data']; return $data; } catch (Exception $e) { return ''; } } //自定义的session的write函数 //expire字段存储的数据为当前时间+session生命期,当这个值小于time()时表明session失效。 function sessionMysqlWrite($sessionId, $data) { try { $dbh = getConnection(); $expire = time() + SESSION_MAXLIFETIME; $sql = 'INSERT INTO `session` (`skey`, `data`, `expire`) ' . 'values (?, ?, ?) ' . 'ON DUPLICATE KEY UPDATE data = ?, expire = ?'; $stmt = $dbh->prepare($sql); $stmt->execute(array($sessionId, $data, $expire, $data, $expire)); } catch (Exception $e) { echo $e->getMessage(); } } //自定义的session的destroy函数 function sessionMysqlDestroy($sessionId) { try { $dbh = getConnection(); $sql = 'DELETE FROM `session` where skey = ?'; $stmt = $dbh->prepare($sql); $stmt->execute(array($sessionId)); return TRUE; } catch (Exception $e) { return FALSE; } } //自定义的session的gc函数 function sessionMysqlGc($lifetime) { try { $dbh = getConnection(); $sql = 'DELETE FROM `session` WHERE expire < ?'; $stmt = $dbh->prepare($sql); $stmt->execute(array(time())); $dbh = NULL; return TRUE; } catch (Exception $e) { return FALSE; } } //自定义的session的session id设置函数 /* * 由于在session_start()之前,SID和session_id()均无效, * 故使用$_GET[session_name()]和$_COOKIE[session_name()]进行检测。 * 如果此两者均为空,则表明session尚未建立,需要为新session设置session id。 * 通过MySQL数据库获取uuid作为session id可以更好的避免session id碰撞。 */ function sessionMysqlId() { if (filter_input(INPUT_GET, session_name()) == '' and filter_input(INPUT_COOKIE, session_name()) == '') { try { $dbh = getConnection(); $stmt = $dbh->query('SELECT uuid() AS uuid'); $data = $stmt->fetch(PDO::FETCH_ASSOC)['uuid']; $data = str_replace('-', '', $data); session_id($data); return TRUE; } catch (Exception $ex) { return FALSE; } } } //session启动函数,包括了session_start()及其之前的所有步骤。 function startSession() { session_set_save_handler( 'sessionMysqlOpen', 'sessionMysqlClose', 'sessionMysqlRead', 'sessionMysqlWrite', 'sessionMysqlDestroy', 'sessionMysqlGc'); register_shutdown_function('session_write_close'); sessionMysqlId(); session_start(); }
二、简介
使用MySQL保存session,需要保存三个关键性的数据:session id、session数据、session生命期。
考虑到session的使用方式,没必要使用InnoDB引擎,MyISAM引擎可以获得更好的性能。如果环境允许,可以尝试使用MEMORY引擎。
保存session数据的列,有需要的话,可以使用utf8或utf8mb4字符集;保存session id的列则没有必要,一般情况使用ascii字符集就可以了,可以节约存储成本。
保存session生命期的列,可以根据工程需要进行设计。比如datetime类型、timestamp类型、int类型。对于datetime、int类型可以保存session生成时间或过期时间。
如果有必要可以扩展session表的列并修改读、写函数以支持(维护)相关列来保存诸如用户名等信息。
当前版本,只要通过session_set_save_handler注册自定义的会话维护函数就可以,不需要在其之前使用session_module_name('user')函数。
当read函数获取数据并返回,PHP会自动对其进行反序列化,一般情况请不要对数据进行更改。
PHP传递给write函数的date参数是序列化之后的session数据,直接保存即可,一般情况请不要对数据进行更改。
按照本段代码的逻辑,PHP配置选项关于会话生命期的设置已经不再有效,这个值可以自行维护,不一定需要通过get_cfg_var获取。
sessionMysqlId()函数是为了避免大用户量、多台Web服务器情况下的碰撞,一般情况PHP自动生成的session id是可以满足用户要求的。
没了
三、需求
当用户量非常大,需要多台服务器提供应用的时候,使用MySQL存储会话相对使用会话文件具有一定的优越性。比如具有最小的存储开销,比如可以避免文件共享带来的复杂性,比如可以更好的避免发生碰撞,比如相比会话文件共享具有更好的性能。总体上来说,当访问量剧增的时候,如果使用数据库保存会话带来的问题是线性增长的,那么使用会话文件带来的问题几乎是爆炸性的。好吧,换一个更直白的说法吧:如果您的应用用户量不大,其实让PHP自己处理session就好了,没必要考虑MySQL。
这个问题,可以用到数组存储,最后输出成分隔的字符串,是多字符串的操作。
我可以发一份示例代码给你。
$gb_DBname="charles_friend";//数据库名称
$gb_DBuser="charles_friend";//数据库用户名称
$gb_DBpass="wxyzoui";//数据库密码
$gb_DBHOSTname="localhost";//主机的名称或是IP地址
$SESS_DBH="";
$SESS_LIFE=get_cfg_var("session.gc_maxlifetime");//得到session的最大有效期。
function sess_open($save_path,$session_name){
global $gb_DBHOSTname,$gb_DBname,$gb_DBuser,$gb_DBpass,$SESS_DBH;
if(!$SESS_DBH=mysql_pconnect($gb_DBHOSTname,$gb_DBuser,$gb_DBpass)){
echo "
die();
}
if(!mysql_select_db($gb_DBname,$SESS_DBH)){
echo "
die();
}
return true;
}
function sess_close(){
return true;
}
function sess_read($key){
global $SESS_DBH,$SESS_LIFE;
$qry="select value from db_session where sesskey = '$key' and expiry > ".time();
$qid=mysql_query($qry,$SESS_DBH);
if(list($value)=mysql_fetch_row($qid)){
return $value;
}
return false;
}
function sess_write($key,$val){
global $SESS_DBH,$SESS_LIFE;
$expiry=time()+$SESS_LIFE;
$value=$val;
$qry="insert into db_session values('$key',$expiry,'$value')";
$qid=mysql_query($qry,$SESS_DBH);
if(!$qid){
$qry="update db_session set expiry=$expiry, value='$value' where sesskey='$key' and expiry >".time();
$qid=mysql_query($qry,$SESS_DBH);
}
return $qid;
} ......余下全文>>

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

웹 응용 프로그램에서 MySQL의 주요 역할은 데이터를 저장하고 관리하는 것입니다. 1. MySQL은 사용자 정보, 제품 카탈로그, 트랜잭션 레코드 및 기타 데이터를 효율적으로 처리합니다. 2. SQL 쿼리를 통해 개발자는 데이터베이스에서 정보를 추출하여 동적 컨텐츠를 생성 할 수 있습니다. 3.mysql은 클라이언트-서버 모델을 기반으로 작동하여 허용 가능한 쿼리 속도를 보장합니다.

Docker에서 MySQL을 시작하는 프로세스는 다음 단계로 구성됩니다. MySQL 이미지를 가져와 컨테이너를 작성하고 시작하고 루트 사용자 암호를 설정하고 포트 확인 연결을 매핑하고 데이터베이스를 작성하고 사용자는 데이터베이스에 모든 권한을 부여합니다.

Laravel은 웹 응용 프로그램을 쉽게 구축하기위한 PHP 프레임 워크입니다. 설치 : Composer를 사용하여 전 세계적으로 Laravel CLI를 설치하고 프로젝트 디렉토리에서 응용 프로그램을 작성하는 등 다양한 기능을 제공합니다. 라우팅 : Routes/Web.php에서 URL과 핸들러 간의 관계를 정의하십시오. 보기 : 리소스/뷰에서보기를 작성하여 응용 프로그램의 인터페이스를 렌더링합니다. 데이터베이스 통합 : MySQL과 같은 데이터베이스와 상자 외 통합을 제공하고 마이그레이션을 사용하여 테이블을 작성하고 수정합니다. 모델 및 컨트롤러 : 모델은 데이터베이스 엔티티를 나타내고 컨트롤러는 HTTP 요청을 처리합니다.

작은 응용 프로그램을 개발할 때 까다로운 문제가 발생했습니다. 가벼운 데이터베이스 운영 라이브러리를 신속하게 통합해야합니다. 여러 라이브러리를 시도한 후에는 기능이 너무 많거나 호환되지 않는다는 것을 알았습니다. 결국, 나는 내 문제를 완벽하게 해결하는 YII2를 기반으로 단순화 된 버전 인 Minii/DB를 발견했습니다.

MySQL 및 Phpmyadmin은 강력한 데이터베이스 관리 도구입니다. 1) MySQL은 데이터베이스 및 테이블을 작성하고 DML 및 SQL 쿼리를 실행하는 데 사용됩니다. 2) PHPMYADMIN은 데이터베이스 관리, 테이블 구조 관리, 데이터 운영 및 사용자 권한 관리에 직관적 인 인터페이스를 제공합니다.

다른 프로그래밍 언어와 비교할 때 MySQL은 주로 데이터를 저장하고 관리하는 데 사용되는 반면 Python, Java 및 C와 같은 다른 언어는 논리적 처리 및 응용 프로그램 개발에 사용됩니다. MySQL은 데이터 관리 요구에 적합한 고성능, 확장 성 및 크로스 플랫폼 지원으로 유명하며 다른 언어는 데이터 분석, 엔터프라이즈 애플리케이션 및 시스템 프로그래밍과 같은 해당 분야에서 이점이 있습니다.

기사 요약 :이 기사는 Laravel 프레임 워크를 쉽게 설치하는 방법에 대한 독자들을 안내하기위한 자세한 단계별 지침을 제공합니다. Laravel은 웹 애플리케이션의 개발 프로세스를 가속화하는 강력한 PHP 프레임 워크입니다. 이 자습서는 시스템 요구 사항에서 데이터베이스 구성 및 라우팅 설정에 이르기까지 설치 프로세스를 다룹니다. 이러한 단계를 수행함으로써 독자들은 라벨 프로젝트를위한 탄탄한 토대를 빠르고 효율적으로 놓을 수 있습니다.

MySQL의 기본 작업에는 데이터베이스, 테이블 작성 및 SQL을 사용하여 데이터에서 CRUD 작업을 수행하는 것이 포함됩니다. 1. 데이터베이스 생성 : createAbasemy_first_db; 2. 테이블 만들기 : CreateTableBooks (idintauto_incrementprimarykey, titlevarchar (100) notnull, authorvarchar (100) notnull, published_yearint); 3. 데이터 삽입 : InsertIntobooks (Title, Author, Published_year) VA
