close

session全教程(二)
--------------------------------------------------------------------------------

  
二、php3,4中session的實現  

在php3中是沒有session這種東東的,但我們又需要,怎麼辦呢?別急,有很多人替你做了這些,
這其中最有名的要算phplib了。你可以去國外下  
載,也可以上國內大部分php站點下載。我們要做的第一件事是讓phplib和php3結合在一起使它能
工作。為了能實現這方面的弁遄A我們需要先安裝phplib。  
跟著我來做,很容易的(以下方法在
win2000+php3.0.16+apache1.3.12+phplib7.2c+mysql3.23.21 for win32 上通過)  
phplib最基本的弁鄍]括用戶認證,Session管理,權限及數據庫的抽像化。  
怎樣使用phplib來實現session弁鄔O?  
一、首先你將phplib解開,裡面有一個目錄叫"php",將這個目錄拷貝到apache的安裝目錄下。以
下以筆者的機器為例:  
我的apache安裝在d:apache 目錄下,我將上面的"php"目錄拷貝到d:apache,並將phplib下的pages
目錄下的文件和目錄一起拷貝到  
d:apachehtdocs下,注意不帶目錄本身。  
phplib的類庫需要根據系統進行初始化,你可以修改local.inc文件,其中包含著一些基本參數,
你可以根據自己機器的實際情況來進行修改。  
將d:apachephpprepend.php3文件中的一段程序改為如下樣子:  

if (!isset($_PHPLIB) or !is_array($_PHPLIB)) { 
$_PHPLIB$"libdir"] = "d:/apache/php/"; //這兒改為你放phplib下php目錄的路徑 

然後將d:apachephplocal.inc文件改如下:

class DB_Example extends DB_Sql { 
var $Host = "localhost";//你的mysql數據庫所在主機名 
var $Database = "test";//數據庫名 
var $User = "root";//數據庫用戶名 
var $Password = "";//數據庫用戶口令 
}

最後一步執行解開的phplib目錄中的stuff目錄下的create_database.mysql文件,生成初始表。  
我們說明一下phplib的工作原理,每一個使用phplib的頁面首先必須可以找到運行phplib所必須
類庫文件,我們可以在php3.ini中設置auto_prepend  
變量來支持,phplib分發包中包含一個prepend.php3文件,將auto_prepend指定
為"d:/apache/php/prepend.php3"(帶引號)後,各頁面就會自動包含phplib類庫,我們還可以  
將phplib類庫所在目錄加進include變量中,以便可以找到這些文件,當然,最苯的辦法就是指定
phplib的絕對路徑,這可不是個好主意,可移植性太差!  
第二步,每一個使用phplib的頁面中,你必須首先調用page_open函數進行初始化。這會告訴
phplib,你現在或將來會用到狀態保存。一個典型的  
page_open例子如下:  

<?php 
page_open(array("sess" => "Example_Session")); 
?>

數組變量(sess)用來初始化一些狀態保存對象,注意:必須使用phplib內置名(sess),這些內置
名是你在local.ini中所定義的,page_open  
函數必須在頁面內容輸出到瀏覽器之前被調用。php3腳本最後應以page_close()結束,這將會將
有關狀態數據寫回到數據庫中,如果你忘了的話,  
結果你應該能想到,哈哈,你的變量全丟了,可不要怪我沒告訴你...  

因為phplib使用了Cookies來保存狀態信息,所以page_open()函數必須在頁面內容輸出到瀏覽器
之前被調用, 這裡的頁面內容可以是任何HTML  
信息或者空行,如果你發現了錯誤&quot;Oops - SetCookie called after header has been sent&quot;,
這表明在page_open()之前向瀏覽器輸出了些什麼,  
你要特別留意空行,因為非常難找到,典型的錯誤是在<? 和 ?>標記之間輸出了空行,你應檢查
在local.inc和prepend.php3文件中是否包含了空行,  
這也是一個非常容易出錯的地方。為了減少出錯的可能,我們可以這樣書寫初始化程序:  

<? 
page_open(array("sess" => "Example_Session")); 
?> 
<html> 
..... 
</html>

第三步,具體使用。  
當一個用戶訪問了該網站後,隨即用戶的session就開始了,如果用戶的瀏覽器支持cookie的話,
將會建立一個session的id放入cookie,  
這個唯一的ID是由PHP3隨機生成,然後又用隨機種子字串進行md5加密過了的,這裡的cookie應該
叫做session cookie,因為這個cookie是不會  
寫到用戶硬盤裡去的,當一個session期結束的時候,該cookie也被完結了。如果用戶瀏覽器不支
持cookie的話,那麼 該session的id將會放入url鏈中,  
因為是加密過的,所以竊取了也沒用。session ID存放著用戶的有關信息,如用戶已認證、認證
到期時間、用戶權限,和其他一些你可能需要的信息,  
方便我們取用。  
Session其實就是用戶一次會話的過程。Session並不是僅僅用來跟蹤用戶的註冊,實際上,它還
可以有其它的使用場合,你可以用它來存儲任何你想要  
存貯的信息,這些信息可以在用戶隨後訪問的頁面中派上用場,當然前提是那些頁面要使用
PHPLIB。方法很簡單,註冊一個變量後即可在隨後的頁面中使用它,  
直至session結束。方法:  

<?php $sess->register( "variable_name"); ?> 

注意,這裡的variable_name不是變量值,而是變量名,可以先指定變量名,隨後再賦值。你在某
個頁面中可以改變變量的值,隨後的頁面訪問該變量時  
會得到改變後的值。變量的類型是多樣的,可以是一個字串,一個數字,一個數組。舉例來說
明:  
第一頁:  

<?php 
page_open(array("sess" => "Example_Session")); 
$sess->register( "first"); //注意變量名前不需要?$ 
if (iset($firstname)) { 
$first = $firstname; 

..... 
page_close(); 
?> 

第二頁:

<?php 
page_open();//開始session 

echo $first;//看看效果 
page_close();//保存狀態信息 
?> 

註冊完一個變量,當頁面最後調用page_close()函數後,各個session變量會被寫回到數據庫中。
如果你忘記調用page_close()函數的話,  
變量就不會被寫回數據庫,將出現不可預知的後果。當變量被使用完畢,你不再需要用到時,可
以調用以下函數將變量刪除

<?php 
page_open(array("sess" => "Example_Session")); 
... 
$sess->unregister( "variable_name"); 
... 
page_close(); 
?> 

PHPLIB 7.0中,使用了一種存儲結構,它允釦A存儲session數據到數據庫中、共享內存中或者
LDAP中。PHPLIB使用了數據庫類,這使得你有  
了更多的選擇,你可以選用oracle8,mysql,postgresql等等數據庫來保存狀態信息。  

關於phplib中的其它弁鄍H及有關session的其它函數的使用,你可以參看它帶的手冊,或上它的
網站看在線文檔。它的老家在  
http://phplib.netuse.de/index.php3 。  
php4的session實現大都從phplib學來的,它也靠cookies保存session id,用文件系統保存變量
(默認情況下)。因此,它的session  
變量不能保存對像(事實上能保存對像內容,但沒有意義,因為它是保存在磁盤上的,不是活的對
象,充其量也就是對像屍體。)不過這點的限制不是太  
大,我們在大部分情況下都只需要保存變量就行了。當然你也可以將session保存在數據庫中,下
一小節中我們會講到怎樣將session保存在數據庫中。  
在php4中由於比php3多了session支持,所以在php.ini文件中也多了session配置選項。下面我們
來看看各項的作用與意義:  

<?session_start()?> 
<html> 
.... 
<body> 
<? 
$var="hello"; 
session_register("var");//註冊$var變量,注意沒有$符號 

if(session_is_registered("var"))//檢查變量是否註冊 
echo "haha,註冊了!"; 
else 
echo "sorry,還沒有註冊!"; 
?> 
</body> 
</html>

php4中session處理的定制  

我們需要擴充6個函數,當然這些函數不需你去調用,對我們來說是透明的。  

這幾個函數是:  
sess_open($sess_path, $session_name);  

這個函數被session處理程序調用來作初始化工作。需要傳給它的兩個參數是$sess_path,它對應
你的php.ini文件中的session.save_path  
選項;$session_name,它對應php.ini中的session.name 選項。它們具體怎樣工作,請看下面的例
子。  

sess_close();  

這個函數在頁面結束執行並且session處理程序需要關閉時被調用。(注意,不要和sess_destory
混淆了,它是用來結束session的)  

sess_read($key);  

這個函數在session處理程序讀取指定session鍵值($key)時。  
這個函數檢索並返回標識為$key的session數據.(注意:你不用擔心怎樣序列化和反序列化數據,
如果你不知道這是什麼意思,不要擔心它)  

譯者註:序列化是將變量或對像在程序結束或需要時保存在文件中,在下次程序運行或需要時再
調入內存的技術,有別於只保存數據的方法。  

sess_write($key, $val);  

這個函數據在session處理程序需要將數據保存時調用,這種情況經常在你的程序結束時發生。  
它負責將數據保存在下次能用sess_read($key)函數檢索的地方。  

sess_destroy($key);  

這個函數在需要消毀session時。它負責刪除session並且清除環境。  


sess_gc($maxlifetime);  
這個函數負責清理碎片。在這種情況下,它負責刪除過時的session數據。session處理程序會偶
爾調用它們。  

現在我們已經清楚了我們提供的函數。  

定製程序可以用mysql數據庫或DBM文件保存session數據。取決於你的需要。  
如果你決定使用mysql作支持,那需要作以下工作:  

首先我們在mysql中創建一個sessions數據庫,並且創建一個sessions表。先運行你的mysql客戶
端並且執行下面的命令:  
mysql> CREATE DATABASE sessions;  

mysql> GRANT select, insert, update, dele ON sessions.* TO phpsession@localhost  
-> IDENTIFIED BY 'phpsession';  

mysql> CREATE TABLE sessions (  
-> sesskey char(32) not null,  
-> expiry int(11) unsigned not null,  
-> value text not null,  
-> PRIMARY KEY (sesskey)  
-> );  

下一步,修改session_mysql.php文件的$SESS_DB* 變量使其匹配你機器上的數據庫設置。  

(很抱歉,由於版權原因,我不能把以下代碼中的英文去掉,只好加些註釋了  
=============================================================

<? 
/* ------------------------------------------------------------------------ 
* session_mysql.php 
* ------------------------------------------------------------------------ 
* PHP4 MySQL Session Handler 
* Version 1.00 
* by Ying Zhang (ying@zippydesign.com
* Last Modified&#58; May 21 2000 

* ------------------------------------------------------------------------ 
* TERMS OF USAGE&#58; 
* ------------------------------------------------------------------------ 
* You are free to use this library in any way you want, no warranties are 
* expressed or implied. This works for me, but I don't guarantee that it 
* works for you, USE AT YOUR OWN RISK. 

* While not required to do so, I would appreciate it if you would retain 
* this header information. If you make any modifications or improvements, 
* please send them via email to Ying Zhang <ying@zippydesign.com>. 

* ------------------------------------------------------------------------ 
* DESCRIPTION&#58; 
* ------------------------------------------------------------------------ 
* This library tells the PHP4 session handler to write to a MySQL database 
* instead of creating individual files for each session. 

* Create a new database in MySQL called "sessions" like so&#58; 

* CREATE TABLE sessions ( 
* sesskey char(32) not null, 
* expiry int(11) unsigned not null, 
* value text not null, 
* PRIMARY KEY (sesskey) 
* ); 

* ------------------------------------------------------------------------ 
* INSTALLATION&#58; 
* ------------------------------------------------------------------------ 
* Make sure you have MySQL support compiled into PHP4. Then copy this 
* script to a directory that is accessible by the rest of your PHP 
* scripts. 
*確信你的php4有mysql支持,然後把這個腳本拷貝到和你的php腳本有關的目錄。 
* ------------------------------------------------------------------------ 
* USAGE&#58;(使用方法) 
* ------------------------------------------------------------------------ 
* Include this file in your scripts before you call session_start(), you 
* don't have to do anything special after that. 
*包含這個文件到你要使用session的文件中,必須在調用session_start()之前,否則, 
*會很慘的,不要怪我沒告訴你。 這樣就不需要再做什麼工作了,還和你以前用session的方法一
樣。 
*/ 
$SESS_DBHOST = "localhost"; /* database server hostname */ 
$SESS_DBNAME = "sessions"; /* database name */ 
$SESS_DBUSER = "phpsession"; /* database user */ 
$SESS_DBPASS = "phpsession"; /* database password */ 
$SESS_DBH = ""; 
$SESS_LIFE = get_cfg_var("session.gc_maxlifetime"); 
function sess_open($save_path, $session_name) { 
global $SESS_DBHOST, $SESS_DBNAME, $SESS_DBUSER, $SESS_DBPASS, $SESS_DBH; 
if (! $SESS_DBH = mysql_pconnect($SESS_DBHOST, $SESS_DBUSER, $SESS_DBPASS)) { 
echo "<li>Can't connect to $SESS_DBHOST as $SESS_DBUSER"; 
echo "<li>MySQL Error&#58; ", mysql_error(); 
die; 

if (! mysql_select_db($SESS_DBNAME, $SESS_DBH)) { 
echo "<li>Unable to select database $SESS_DBNAME"; 
die; 

return true; 

function sess_close() { 
return true; 

function sess_read($key) { 
global $SESS_DBH, $SESS_LIFE; 
$qry = "SELECT value FROM sessions 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 = addslashes($val); 
$qry = "INSERT INTO sessions VALUES ('$key', $expiry, '$value')"; 
$qid = mysql_query($qry, $SESS_DBH); 
if (! $qid) { 
$qry = "UPDATE sessions SET expiry = $expiry, value = '$value' WHERE sesskey 
= '$key' AND expiry > " . time(); 
$qid = mysql_query($qry, $SESS_DBH); 

return $qid; 

function sess_destroy($key) { 
global $SESS_DBH; 
$qry = "DELETE FROM sessions WHERE sesskey = '$key'"; 
$qid = mysql_query($qry, $SESS_DBH); 
return $qid; 

function sess_gc($maxlifetime) { 
global $SESS_DBH; 
$qry = "DELETE FROM sessions WHERE expiry < " . time(); 
$qid = mysql_query($qry, $SESS_DBH); 
return mysql_affected_rows($SESS_DBH); 

session_set_save_handler( 
"sess_open", 
"sess_close", 
"sess_read", 
"sess_write", 
"sess_destroy", 
"sess_gc"); 
?> 

=================================================================  
具體怎麼用就不用多說了,因為這些函數都是php引擎調用的,與我們無關的。我們只需照上述配
置後就行了,你用的還是以前的session函數。  
看看下面的代碼就知道了:)  


session定制的測試代碼  
==================================================================  

<? 
/* ------------------------------------------------------------------------ 
* test.php 
* ------------------------------------------------------------------------ 
* PHP4 Customer Session Handler Test Script 
* Version 1.00 
* by Ying Zhang (ying@zippydesign.com
* Last Modified&#58; May 21 2000 
*/ 
/* default to DBM handler */ 
if (! isset($handler)) { 
$handler = "dbm"; 

/* default action is increment */ 
if (! isset($action)) { 
$action = "increment"; 

/* load up the appropriate session handling script, depending on the handler */ 
if ($handler == "dbm") { 
include("session_dbm.php"); 
} elseif ($handler == "mysql") { 
include("session_mysql.php"); 
} else { 
echo "<li>Unrecognized handler ($handler)"; 
die; 

/* start the session and register a simple counter */ 
session_start(); 
session_register("count"); 
/* figure out what we should do, depending on the action */ 
switch ($action) { 
case "increment" &#58; 
$count = isset($count) ? $count + 1 &#58; 0; 
break; 
case "destroy" &#58; 
session_destroy(); 
break; 
case "gc" &#58; 
$maxlife = get_cfg_var("session.gc_maxlifetime"); 
sess_gc($maxlife); 
break; 
default&#58; 
echo "<li>Unknown action ($action)"; 
break; 

?> 
<h1>Session Test Script</h1> 
<ul> 
<li>Handler&#58; <b><?=$handler?></b> 
<li>Action&#58; <b><?=$action?></b> 
<li>Count&#58; <b><?=$count?></b> 
</ul> 
<hr size=1> 
<form> 
<table> 
<tr> 
<td>Handler&#58;</td> 
<td> 
<select name="handler"> 
<option value="dbm">DBM</option> 
<option value="mysql">MySQL</option> 
</select> 
</td> 
</tr> 
<tr> 
<td>Action&#58;</td> 
<td> 
<select name="action"> 
<option value="increment">Increment</option> 
<option value="destroy">Session Destroy</option> 
<option value="gc">Force Garbage Collection</option> 
</select> 
</td> 
</tr> 
<tr> 
<td></td> 
<td><br><input type="submit"></td> 
</tr> 
</table> 
</form> 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Hsiu 的頭像
    Hsiu

    Hsiu的部落格

    Hsiu 發表在 痞客邦 留言(0) 人氣()