Session指的是使用者在瀏覽某個網站時,從進入網站到瀏覽器關閉所經過的這段時間,也就是使用者瀏覽這個網站所花費的時間。從上述的定義中我們可以看到,Session其實是一個特定的時間概念。
一般來說,在網站上某一個頁面中的變數(指伺服器端變量,下同)是不能在下一頁中用的,有了session就好辦了。 session中註冊的變數可以當作全域變數使用。這樣我們就可以將session用於使用者身分認證,程式狀態記錄,頁面之間參數傳遞。
在PHP3版本是如何實現session的?
php3本身是沒有實作session功能的,我們只有用其他的方法來實作,這其中最有名的要算phplib了。 phplib最基本的功能包括使用者認證、Session管理、權限及資料庫的抽象化。下面我們就來講述一下如何用phplib實作session。
1.先安裝phplib(環境為win2000+php3.0.16+Apache1.3.12+phplib7.2c+mysql3.23.21 for win32)
先將phplib解開,裡面有一個"php"目錄,將這個目錄拷貝到Apache的安裝目錄下。例如:Apache安裝在d:Apache 目錄下,那麼就將"php"目錄拷貝到d:Apache,並將phplib目錄的pages目錄下(不包括目錄本身)的檔案和目錄一起拷貝到d: Apachehtdocs下。
phplib的類別庫需要根據系統進行初始化,可能需要修改local.inc檔,其中包含著一些基本參數,可以根據自己機器的實際情況來進行修改。
將d:Apachephpprepend.php檔案中的一段程式改為如下樣子:
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 = "1234567"; //資料庫使用者密碼
}
最後根據phplib目錄下的stuff子目錄中的create_database.mysql檔案產生初始表。
由於每一個使用phplib的頁面首先必須可以找到運行phplib所必需的類別庫文件,我們可以在php.ini中設置auto_prepend變數來支援,phplib中包含一個prepend.php文件,並將auto_prepend指定為"d: /Apache/php/prepend.php"(帶引號)後,各頁就會自動包含phplib類別庫,我們也可以將phplib類別庫所在目錄加進include變數中,以便可以找到這些檔案。 2.呼叫page_open()函數
在每一個使用phplib的頁面中,必須先呼叫page_open函數進行初始化,例如:
<?php
page_open(array("sess" => "Test_Session"));
?>
數組變數(sess)用來初始化一些狀態保存物件,這裡應該注意:必須使用phplib內建名(sess),這些內建名是在local.inc中所定義的.。
因為phplib使用了Cookies來保存狀態資訊,所以page_open()函數必須在頁面內容輸出到瀏覽器之前被呼叫。 php腳本最後應以page_close()結束,這將會將有關狀態資料寫回資料庫,否則變數會遺失。
3、具體使用。
註冊一個變數後即可在隨後的頁面中使用它,直到session結束。方法:
<?php $sess->register( "varname"); ?>
注意,這裡的varname不是變數值,而是變數名,可以先指定變數名,隨後再賦值。你在某個頁面中可以改變變數的值,隨後的頁面訪問該變數時會得到改變後的值。變數的型別是多樣的,可以是一個字串,一個數字,一個陣列。舉例來說明:
第一頁:
<?php
page_open(array("sess" => "Test _Session"));
$sess->register( "welcome"); //註冊變數$welcome,注意不需要加$
$welcome="Hello,PHP world!";
……
page_close();
?>
第二頁:
<?php
page_open();//開始session
echo $welcome;//顯示第一頁中定義的$welcome
page_close();//保存狀態資訊
?>
註冊完一個變量,當頁面最後呼叫page_close()函數後,各個session變數會寫回資料庫。如果忘記呼叫page_close()函數的話,變數就不會被寫回資料庫,這樣將出現不可預測的後果。當變數被使用完畢,不再需要用到時,可以呼叫以下函數將變數刪除:
<?php
page_open(array("sess" => "Test _Session"));
……
$sess->unregister( "variable_name");
……
page_close();
?>
在PHP4版中是如何實現session的?
php4的session也靠cookies保存session id,用檔案系統保存變數(預設),因此,它的session變數不能儲存物件。當然也可以將session保存在資料庫中。
在php4中有關session的函數很多(詳見php.ini配置一文),通常情況下我們只需要呼叫三個函數即可:sesssion_start()、session_register()、session_is_registered()。
在需要用到session的每一頁的最開始處呼叫session_start()函數, 例如:
<?session_start()?>
<html><body>
<?
$welcome="hello world !";
session_register("welcome");//註冊$welcome變數,注意沒有$符號if(session_is_registered("welcome"))//檢查$welcome變數是否註冊echo "welcome變數已經註冊了!";
else
echo "welcome變數還沒註冊!";
?>
</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_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> CREATE DATABASE sessions;
mysql> GRANT select, insert, update, delete 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* 變數使其符合你機器上的資料庫設定:
<?
$SESS_DBHOST = "localhost"; /* 資料庫主機名稱*/
$SESS_DBNAME = "sessions"; /* 資料庫名稱*/
$SESS_DBUSER = "phpsession"; /* 資料庫使用者名稱*/
$SESS_DBPASS = "phpsession"; /* 資料庫密碼*/
$SESS_DBH = "";
$SESS_LIFE = get_cfg_var("session.gc_maxlifetime");
……//自訂函數
session_set_save_handler( "sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
?>
定制使用dbm檔案時的介面:
<?
$SESS_DBM = "";
$SESS_LIFE = get_cfg_var("session.gc_maxlifetime");
……//自訂函數
session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
?>
session定制的測試程式碼:
<?php
……
if ($handler == "dbm") include("session_dbm.php");//使用何種接口
elseif ($handler == "mysql") include("session_mysql.php");
else ……
session_start();
session_register("count");
……
?>
在身分驗證中,如何應用Session?
Session可以用於使用者認證:
驗證使用者是否合法:
<?
session_start();
……//驗證過程session_register("reguser");
?>
在另一頁檢查使用者是否登入
<?
session_start();
if(isset($reguser)&&$reguser!=""){//如果已經登入echo "親愛的使用者,歡迎你";
}else{//如果沒有登入echo "請先註冊!";
}
?>
用戶登出登入:
<?
session_destroy();
……
?>
如何實現多session並發運作?
問題提出:我在為所在單位編寫一個進銷存系統中發現需要讓多個使用者可以同時進入一個php應用程式。原來設計的靜態的唯一的session ID導致資料混亂。這樣,動態產生一個唯一的session ID成為當務之急。
解決方法很簡單:我用了php檔名+時間戳為唯一的session ID,這樣在我的程式中的每個session就各就各位,不再混亂了。
下面把我的原始碼公佈,方便也有同樣的問題的朋友多一個解決方法。
//Start a PHP session to preserve variables.
if ( empty($mysessionname) ) {
$micro = microtime();
$micro = str_replace(" ","",$micro); // strip out the blanks
$micro = str_replace(".","",$micro); // strip out the periods
$mysessionname = "po_maint" . $micro;
}
session_name($mysessionname);
session_start();
程式註解:
用mysessionname為頁間唯一的sessionname傳遞變量,如果你也用到這個名字必須把上述程式做個小小的改動。 Mysessionname不能為session的內部變數名,因為他在session開始之前就已經存在了。 Mysessionname也不能用cookie方式存放,因為多個session一定會覆寫原來的cookie檔。你可以用隱含表單的網域來保存它。這樣就不會有問題。