現在程式員愈發的不容易了,想要精通,必然要尋本溯源,這其實與目前泛濫的愈發高級的語言以及眾多的框架剛好相反,因為它們在儘可能的掩蓋本源使其簡單,個人稱之為程式員學習悖論。 註:作者接觸web開發和php兩周左右,以下內容適合初學者。 1、導讀 從文題目看,<簡單PHP會話(Session)說明> 是 ...
現在程式員愈發的不容易了,想要精通,必然要尋本溯源,這其實與目前泛濫的愈發高級的語言以及眾多的框架剛好相反,因為它們在儘可能的掩蓋本源使其簡單,個人稱之為程式員學習悖論。
註:作者接觸web開發和php兩周左右,以下內容適合初學者。
1、導讀
從文題目看,<簡單PHP會話(Session)說明> 是已經圈定了本文的內容範圍,試圖闡明Session(文中對會話稱為Session) 在PHP語言中是如何實現以及使用的,重點在於基本理解後的使用。 文章思路是首先搞清楚session是什麼東西,Session有什麼用,Session使用的套路是什麼,PHP中是如何使用的。2、會話(Session)說明
開始前,首先推薦一本基礎理論書《HTTP權威指南》,是程式員基礎必備知識,作者有電子版,有需要的可以留言。a. Session的由來
幾乎每個人都上網,數以億計的數據在網路中相互傳輸,數據之所以能夠安全的傳輸,是基於HTTP協議的,很是耳熟能詳是吧。其實HTTP協議所乾的事情就是提供完成你的網路訪問一系列方法,雙方構建了一次訪問,原則上就是一個會話建立了。說一個例子:小明在瀏覽器中輸入https://www.baidu.com/(HTTPS是HTTP的加密版本,相比是增加了SSL加密層),這是小明對百度發起了一個請求,說:“我要看你的界面”,百度的伺服器們收到信息,信息中包括了小名想乾的事情,同時包括了小明的地址(否則百度不知道把內容給誰了),伺服器核對信息OK,對小明這個請求進行備案,發送出小名想要的東西,一次完整的請求結束了。 這就是一次會話,會話的核心在於小明的信息備案(其實還涉及到TCP/IP的連接問題,這個與本文無關,忽略)。 其實與其說是構建了一個Session,倒不如說將一次訪問概括為一個Session。b. Session能幹什麼用
從上面內容可以得到,每一個訪問都是一個會話,伺服器都要備案信息,這是有開銷的,同時呢,也不大可能同一個人連續訪問十次二十次就構建保存十次二十次,一個是增加開銷,另一個是也比較蠢了。也就是說,一個人(確切說是同一個電腦和瀏覽器),在某個特定時間內,能夠復用一個Session的,為什麼在特定時間內呢?因為Session是有預設的過期時間,過期後伺服器就清理掉了(如果不這樣,你想想世界那麼多人,來一個保留一個,太虧)。 ok,既然同一個人,多次訪問都是一個Session(不要懷疑伺服器無法判別是同一個人,具體可以看上面推介的書),而且每次訪問的內容都是做備案的,那麼也就是說,你Session周期內所有的行為伺服器都是知道的,那麼接下來重要的作用就來了,伺服器通過對你的訪問請求分析,能夠獲知到這個特定用戶的行為偏好的,通過做一定的分析,能夠推送一些用戶喜歡關心的數據,廣告定向也就是這麼來的。 當然可能還有其他的用戶,性能等等之類的,個人不是特別理解機理,這裡就這樣。3、PHP中Session的使用
通過上面的啰嗦,可以發現,Session這個概念其實是在伺服器端發生的。PHP提供了一系列的配置、函數等,很好的實現Session功能。Session支持在 PHP 中是在併發訪問時由一個方法來保存某些數據.從而使你能夠構建更多的定製程式 從而提高你的 web 網站的吸引力. 一個訪問者訪問你的 web 網站將被分配一個唯一的 id, 就是所謂的session id. 這個 id 可以存儲在用戶端的一個 cookie 中,也可以通過 URL 進行傳遞.會話支持允許你將請求中的數據保存在超全局數組$_SESSION中. 當一個訪問者訪問你的網站,PHP 將自動檢查(如果 session.auto_start 被設置為 1)或者在你要求下檢查(明確通過session_start()或者隱式通過session_register()) 當前session id 是否是先前發送的請求創建. 如果是這種情況, 那麼先前保存的環境將被重建.a. php中session基本用法
通過為每個獨立用戶分配唯一的Session ID,可以實現針對不同用戶分別存儲數據的功能。 會話通常被用來在多個頁面請求之間保存及共用信息。 一般來說,Session ID 通過 cookie 的方式發送到瀏覽器,並且在伺服器端也是通過會話 ID 來取回會話中的數據。 如果請求中不包含會話 ID 信息,那麼 PHP 就會創建一個新的Session,併為新創建的Session分配新的 ID。 Session的工作流程很簡單。當開始一個Session時,PHP 會嘗試從請求中查找Session ID (通常通過Session cookie), 如果請求中不包含Session ID 信息,PHP 就會創建一個新的Session。 Session開始之後,PHP 就會將Session中的數據設置到 $_SESSION變數中。 當 PHP 停止的時候,它會自動讀取$_SESSION中的內容,並將其進行序列化, 然後發送給會話保存管理器器來進行保存。預設情況下,PHP 使用內置的文件Session保存管理器(files
)來完成Session的保存。 也可以通過配置項session.save_handler(php.ini中配置項目)來修改所要採用的Session保存管理器。 對於文件Session保存管理器,Session會話數據保存到配置項session.save_path (php.ini中配置項目)所指定的位置。可以通過調用函數session_start來手動開始一個會話。 如果配置項session.auto_start 設置為1
, 那麼請求開始的時候,Session會自動開始。PHP 腳本執行完畢之後,session會自動關閉。 同時,也可以通過調用函數session_wirte_close() 來手動關閉會話。
b. php中session信息在php.ini中配置
這部分內容放在這裡說是因為,不說明前面問題,鬼知道php.ini中的配置是什麼東西。 上面提到的session.save_handler和session.save_path,這兩個就是php.ini中的配置項目,這裡面這塊不細說,因為php手冊實在是太詳細了。本文預設模式是files。c. php中的session機制
session_start()是session機制的開始,session會判斷當前是否有$_COOKIE[session_name()];session_name()返回保存session_id的COOKIE鍵值,如果不存在會生成一個session_id,然後把生成的session_id作為COOKIE的值傳遞到客戶端.相當於執行了下麵COOKIE 操作。相反,如果存在session_id =$_COOKIE[session_name];然後去session.save_path指定的文件夾里去找名字為'SESS_'.session_id()的文件.讀取文件的內容反序列化,然後放到$_SESSION中。 在會話結束的時候,會執行Session寫入操作或是手工執行session_write_close()操作。 代碼裡面銷毀Session一般有三個方法, 1. setcookie(session_name(),session_id(),time() -8000000,..); //退出登錄前執行2. usset($_SESSION); //這會刪除所有的$_SESSION數據,刷新後,有COOKIE傳過來,但是沒有數據。
3. session_destroy(); //刪除$_SESSION 刪除session文件以及session_id
附錄,引用網路上的一段代碼,作為結尾吧。
<span style="white-space:pre"> </span>//SESSION初始化的時候調用 function open($save_path, $session_name) { global $sess_save_path; $sess_save_path=$save_path; return(true); } //關閉的時候調用 function close() { return(true); } function read($id) { global $sess_save_path; $sess_file="$sess_save_path/sess_$id"; return (string) @file_get_contents($sess_file); } //腳本執行結束之前,執行寫入操作 function write($id,$sess_data) { global$sess_save_path; $sess_file="$sess_save_path/sess_$id"; if ($fp= @fopen($sess_file,"w")) { $return=fwrite($fp,$sess_data); fclose($fp); return$return; } else { return(false); } } function destroy($id) { global $sess_save_path; $sess_file="$sess_save_path/sess_$id"; return(@unlink($sess_file)); } function gc($maxlifetime) { global$sess_save_path; foreach (glob("$sess_save_path/sess_*") as$filename) { if (filemtime($filename) +$maxlifetime<time()) { @unlink($filename); } } return true; }