Session(會話)類可以讓你保持一個用戶的 "狀態(tài)" ,并跟蹤他在瀏覽你的網(wǎng)站時的活動。
CodeIgniter 自帶了幾個存儲 session 的驅(qū)動:
另外,你也可以基于其他的存儲機制來創(chuàng)建你自己的自定義 session 存儲驅(qū)動, 使用自定義的驅(qū)動,同樣也可以使用 Session 類提供的那些功能。
[TOC=2.3]
Session 通常會在每個頁面載入的時候全局運行,所以 Session 類必須首先被初始化。 您可以在 控制器 的構(gòu)造函數(shù)中初始化它, 也可以在系統(tǒng)中 自動加載。Session 類基本上都是在后臺運行, 你不會注意到。所以當初始化 session 之后,系統(tǒng)會自動讀取、創(chuàng)建和更新 session 數(shù)據(jù) 。
要手動初始化 Session 類,你可以在控制器的構(gòu)造函數(shù)中使用 $this->load->library() 方法:
$this->load->library('session');
初始化之后,就可以使用下面的方法來訪問 Session 對象了:
$this->session
重要
由于 加載類 是在 CodeIgniter 的控制器基類中實例化的, 所以如果要在你的控制器構(gòu)造函數(shù)中加載類庫的話,確保先調(diào)用 parent::__construct()方法。
當頁面載入后,Session 類就會檢查用戶的 cookie 中是否存在有效的 session 數(shù)據(jù)。 如果 session 數(shù)據(jù)不存在(或者與服務端不匹配,或者已經(jīng)過期), 那么就會創(chuàng)建一個新的 session 并保存起來。
如果 session 數(shù)據(jù)存在并且有效,那么就會更新 session 的信息。 根據(jù)你的配置,每一次更新都會生成一個新的 Session ID 。
有一點非常重要,你需要了解一下,Session 類一旦被初始化,它就會自動運行。 上面所說的那些,你完全不用做任何操作。正如接下來你將看到的那樣, 你可以正常的使用 session 數(shù)據(jù),至于讀、寫和更新 session 的操作都是自動完成的。
注解
在 CLI 模式下,Session 類將自動關閉,這種做法完全是基于 HTTP 協(xié)議的。
如果你開發(fā)的網(wǎng)站并不是大量的使用 AJAX 技術(shù),那么你可以跳過這一節(jié)。 如果你的網(wǎng)站是大量的使用了 AJAX,并且遇到了性能問題,那么下面的注意事項, 可能正是你需要的。
在 CodeIgniter 之前的版本中,Session 類并沒有實現(xiàn)鎖機制,這也就意味著, 兩個 HTTP 請求可能會同時使用同一個 session 。說的更專業(yè)點就是, 請求是非阻塞的。(requests were non-blocking)
在處理 session 時使用非阻塞的請求同樣意味著不安全,因為在一個請求中修改 session 數(shù)據(jù)(或重新生成 Session ID)會對并發(fā)的第二個請求造成影響。這是導致很多問題的根源, 同時也是為什么 CodeIgniter 3.0 對 Session 類完全重寫的原因。
那么為什么要告訴你這些呢?這是因為在你查找性能問題的原因時, 可能會發(fā)現(xiàn)加鎖機制正是導致性能問題的罪魁禍首,因此就想著如何去掉鎖 ...
請不要這樣做! 去掉加鎖機制是完全錯誤的,它會給你帶來更多的問題!
鎖并不是問題,它是一種解決方案。你的問題是當 session 已經(jīng)處理完畢不再需要時, 你還將 session 保持是打開的狀態(tài)。所以,你需要做的其實是,當結(jié)束當前請求時, 將不再需要的 session 關閉掉。
簡單來說就是:當你不再需要使用某個 session 變量時,就使用 session_write_close() 方法來關閉它。
Session 數(shù)據(jù)是個簡單的數(shù)組,帶有一個特定的 session ID (cookie)。
如果你之前在 PHP 里使用過 session ,你應該對 PHP 的 $_SESSION 全局變量 很熟悉(如果沒有,請閱讀下鏈接中的內(nèi)容)。
CodeIgniter 使用了相同的方式來訪問 session 數(shù)據(jù),同時使用了 PHP 自帶的 session 處理機制, 使用 session 數(shù)據(jù)和操作 $_SESSION 數(shù)組一樣簡單(包括讀取,設置,取消設置)。
另外,CodeIgniter 還提供了兩種特殊類型的 session 數(shù)據(jù):flashdata 和 tempdata ,在下面將有介紹。
注解
在之前的 CodeIgniter 版本中,常規(guī)的 session 數(shù)據(jù)被稱之為 'userdata' ,當文檔中出現(xiàn)這個詞時請記住這一點。 大部分都是用于解釋自定義 'userdata' 方法是如何工作的。
session 數(shù)組中的任何信息都可以通過 $_SESSION 全局變量獲取:
$_SESSION['item']
或使用下面的方法(magic getter):
$this->session->item
同時,為了和之前的版本兼容,也可以使用 userdata() 方法:
$this->session->userdata('item');
其中,item 是你想獲取的數(shù)組的鍵值。例如,將 'name' 鍵值對應的項賦值給 $name 變量, 你可以這樣:
$name = $_SESSION['name'];
// or:
$name = $this->session->name
// or:
$name = $this->session->userdata('name');
注解
如果你訪問的項不存在,userdata() 方法返回 NULL 。
如果你想獲取所有已存在的 userdata ,你可以忽略 item 參數(shù):
$_SESSION
// or:
$this->session->userdata();
假設某個用戶訪問你的網(wǎng)站,當他完成認證之后,你可以將他的用戶名和 email 地址添加到 session 中, 這樣當你需要的時候你就可以直接訪問這些數(shù)據(jù),而無法查詢數(shù)據(jù)庫了。
你可以簡單的將數(shù)據(jù)賦值給 $_SESSION 數(shù)組,或賦值給 $this->session 的某個屬性。
同時,老版本中的通過 "userdata" 來賦值的方法也還可以用,只不過是需要傳遞一個包含你的數(shù)據(jù)的數(shù)組 給 set_userdata() 方法:
$this->session->set_userdata($array);
其中,$array 是包含新增數(shù)據(jù)的一個關聯(lián)數(shù)組,下面是個例子:
$newdata = array(
'username' => 'johndoe',
'email' => 'johndoe@some-site.com',
'logged_in' => TRUE
);
$this->session->set_userdata($newdata);
如果你想一次只添加一個值,set_userdata() 也支持這種語法:
$this->session->set_userdata('some_name', 'some_value');
如果你想檢查某個 session 值是否存在,可以使用 isset():
// returns FALSE if the 'some_name' item doesn't exist or is NULL,
// TRUE otherwise:
isset($_SESSION['some_name'])
或者,你也可以使用 has_userdata():
$this->session->has_userdata('some_name');
和其他的變量一樣,可以使用 unset() 方法來刪除 $_SESSION 數(shù)組中的某個值:
unset($_SESSION['some_name']);
// or multiple values:
unset(
$_SESSION['some_name'],
$_SESSION['another_name']
);
同時,正如 set_userdata() 方法可用于向 session 中添加數(shù)據(jù),unset_userdata() 方法可用于刪除指定鍵值的數(shù)據(jù)。例如,如果你想從你的 session 數(shù)組中刪除 'some_name':
$this->session->unset_userdata('some_name');
這個方法也可以使用一個數(shù)組來同時刪除多個值:
$array_items = array('username', 'email');
$this->session->unset_userdata($array_items);
注解
在 CodeIgniter 之前的版本中,unset_userdata() 方法接受一個關聯(lián)數(shù)組, 包含 key => 'dummy value' 這樣的鍵值對,這種方式不再支持。
CodeIgniter 支持 "flashdata" ,它指的是一種只對下一次請求有效的 session 數(shù)據(jù), 之后將會自動被清除。
這用于一次性的信息時特別有用,例如錯誤或狀態(tài)信息(諸如 "第二條記錄刪除成功" 這樣的信息)。
要注意的是,flashdata 就是常規(guī)的 session 變量,只不過以特殊的方式保存在 '__ci_vars' 鍵下 (警告:請不要亂動這個值)。
將已有的值標記為 "flashdata":
$this->session->mark_as_flash('item');
通過傳一個數(shù)組,同時標記多個值為 flashdata:
$this->session->mark_as_flash(array('item', 'item2'));
使用下面的方法來添加 flashdata:
$_SESSION['item'] = 'value';
$this->session->mark_as_flash('item');
或者,也可以使用 set_flashdata() 方法:
$this->session->set_flashdata('item', 'value');
你還可以傳一個數(shù)組給 set_flashdata() 方法,和 set_userdata() 方法一樣。
讀取 flashdata 和讀取常規(guī)的 session 數(shù)據(jù)一樣,通過 $_SESSION 數(shù)組:
$_SESSION['item']
重要
userdata() 方法不會返回 flashdata 數(shù)據(jù)。
如果你要確保你讀取的就是 "flashdata" 數(shù)據(jù),而不是其他類型的數(shù)據(jù),可以使用 flashdata() 方法:
$this->session->flashdata('item');
或者不傳參數(shù),直接返回所有的 flashdata 數(shù)組:
$this->session->flashdata();
注解
如果讀取的值不存在,flashdata() 方法返回 NULL 。
如果你需要在另一個請求中還繼續(xù)保持 flashdata 變量,你可以使用 keep_flashdata() 方法。 可以傳一個值,或包含多個值的一個數(shù)組。
$this->session->keep_flashdata('item');
$this->session->keep_flashdata(array('item1', 'item2', 'item3'));
CodeIgniter 還支持 "tempdata" ,它指的是一種帶有有效時間的 session 數(shù)據(jù), 當它的有效時間已過期,或在有效時間內(nèi)被刪除,都會自動被清除。
和 flashdata 一樣, tempdata 也是常規(guī)的 session 變量,只不過以特殊的方式保存在 '__ci_vars' 鍵下 (再次警告:請不要亂動這個值)。
將已有的值標記為 "tempdata" ,只需簡單的將要標記的鍵值和過期時間(單位為秒)傳給 mark_as_temp() 方法即可:
// 'item' will be erased after 300 seconds
$this->session->mark_as_temp('item', 300);
你也可以同時標記多個值為 tempdata ,有下面兩種不同的方式, 這取決于你是否要將所有的值都設置成相同的過期時間:
// Both 'item' and 'item2' will expire after 300 seconds
$this->session->mark_as_temp(array('item', 'item2'), 300);
// 'item' will be erased after 300 seconds, while 'item2'
// will do so after only 240 seconds
$this->session->mark_as_temp(array(
'item' => 300,
'item2' => 240
));
使用下面的方法來添加 tempdata:
$_SESSION['item'] = 'value';
$this->session->mark_as_temp('item', 300); // Expire in 5 minutes
或者,也可以使用 set_tempdata() 方法:
$this->session->set_tempdata('item', 'value', 300);
你還可以傳一個數(shù)組給 set_tempdata() 方法:
$tempdata = array('newuser' => TRUE, 'message' => 'Thanks for joining!');
$this->session->set_tempdata($tempdata, NULL, $expire);
注解
如果沒有設置 expiration 參數(shù),或者設置為 0 ,將默認使用 300秒(5分鐘)作為生存時間(time-to-live)。
要讀取 tempdata 數(shù)據(jù),你可以再一次通過 $_SESSION 數(shù)組:
$_SESSION['item']
重要
userdata() 方法不會返回 tempdata 數(shù)據(jù)。
如果你要確保你讀取的就是 "tempdata" 數(shù)據(jù),而不是其他類型的數(shù)據(jù),可以使用 tempdata() 方法:
$this->session->tempdata('item');
或者不傳參數(shù),直接返回所有的 tempdata 數(shù)組:
$this->session->tempdata();
注解
如果讀取的值不存在,tempdata() 方法返回 NULL 。
如果你需要在某個 tempdata 過期之前刪除它,你可以直接通過 $_SESSION 數(shù)組來刪除:
unset($_SESSION['item']);
但是,這不會刪除這個值的 tempdata 標記(會在下一次 HTTP 請求時失效),所以, 如果你打算在相同的請求中重用這個值,你可以使用unset_tempdata():
$this->session->unset_tempdata('item');
要清除當前的 session(例如:退出登錄時),你可以簡單的使用 PHP 自帶的 session_destroy() 函數(shù)或者 sess_destroy() 方法。 兩種方式效果完全一樣:
session_destroy();
// or
$this->session->sess_destroy();
注解
這必須是同一個請求中關于 session 的最后一次操作,所有的 session 數(shù)據(jù)(包括 flashdata 和 tempdata)都被永久性銷毀,銷毀之后,關于 session 的方法將不可用。
在之前的 CodeIgniter 版本中,session 數(shù)據(jù)默認包含 4 項:'session_id' 、 'ip_address' 、 'user_agent' 、 'last_activity' 。
這是由 session 具體的工作方式?jīng)Q定的,但是我們現(xiàn)在的實現(xiàn)沒必要這樣做了。 盡管如此,你的應用程序可能還依賴于這些值,所以下面提供了訪問這些值的替代方法:
- session_id: session_id()
- ip_address: $_SERVER['REMOTE_ADDR']
- user_agent: $this->input->user_agent() (unused by sessions)
- last_activity: 取決于 session 的存儲方式,沒有直接的方法,抱歉!
在 CodeIgniter 中通常所有的東西都是拿來直接就可以用的,盡管如此,session 對于所有的程序來說, 都是一個非常敏感的部分,所以必須要小心的配置它。請花點時間研究下下面所有的選項以及每個選項的作用。
你可以在你的配置文件 application/config/config.php 中找到下面的關于 session 的配置參數(shù):
參數(shù) | 默認值 | 選項 | 描述 |
---|---|---|---|
sess_driver | files | files/database/redis/memcached/custom | 使用的存儲 session 的驅(qū)動 |
sess_cookie_name | ci_session | [A-Za-z_-] characters only | session cookie 的名稱 |
sess_expiration | 7200 (2 hours) | Time in seconds (integer) | 你希望 session 持續(xù)的秒數(shù) 如果你希望 session 不過期(直到瀏覽器關閉),將其設置為 0 |
sess_save_path | NULL | None | 指定存儲位置,取決于使用的存儲 session 的驅(qū)動 |
sess_match_ip | FALSE | TRUE/FALSE (boolean) | 讀取 session cookie 時,是否驗證用戶的 IP 地址 注意有些 ISP 會動態(tài)的修改 IP ,所以如果你想要一個不過期的 session,將其設置為 FALSE |
sess_time_to_update | 300 | Time in seconds (integer) | 該選項用于控制過多久將重新生成一個新 session ID 設置為 0 將禁用 session ID 的重新生成 |
sess_regenerate_destroy | FALSE | TRUE/FALSE (boolean) | 當自動重新生成 session ID 時,是否銷毀老的 session ID 對應的數(shù)據(jù) 如果設置為 FALSE ,數(shù)據(jù)之后將自動被垃圾回收器刪除 |
注解
如果上面的某個參數(shù)沒有配置,Session 類將會試圖讀取 php.ini 配置文件中的 session 相關的配置 (例如 'sess_expire_on_close')。但是,請不要依賴于這個行為,因為這可能會導致不可預期的結(jié)果,而且 這也有可能在未來的版本中修改。請合理的配置每一個參數(shù)。
除了上面的這些參數(shù)之外,cookie 和 session 原生的驅(qū)動還會公用下面這些 由 輸入類 和 安全類 提供的配置參數(shù)。
參數(shù) | 默認值 | 描述 |
---|---|---|
cookie_domain | '' | session 可用的域 |
cookie_path | / | session 可用的路徑 |
cookie_secure | FALSE | 是否只在加密連接(HTTPS)時創(chuàng)建 session cookie |
注解
'cookie_httponly' 配置對 session 沒有影響。出于安全原因,HttpOnly 參數(shù)將一直啟用。 另外,'cookie_prefix' 參數(shù)完全可以忽略。
正如上面提到的,Session 類自帶了 4 種不同的驅(qū)動(或叫做存儲引擎)可供使用:
- files
- database
- redis
- memcached
默認情況下,初始化 session 時將使用 文件驅(qū)動 ,因為這是最安全的選擇,可以在所有地方按預期工作 (幾乎所有的環(huán)境下都有文件系統(tǒng))。
但是,你也可以通過 application/config/config.php 配置文件中的 $config['sess_driver'] 參數(shù)來使用任何其他的驅(qū)動。特別提醒的是,每一種驅(qū)動都有它自己的注意事項,所以在你選擇之前, 確定你熟悉它們。
另外,如果默認提供的這些不能滿足你的需求,你也可以創(chuàng)建和使用 自定義驅(qū)動 。
注解
在之前版本的 CodeIgniter 中,只有 "cookie 驅(qū)動" 這唯一的一種選擇, 因為這個我們收到了大量的負面的反饋。因此,我們吸取了社區(qū)的反饋意見,同時也要提醒你, 因為它不安全,所以已經(jīng)被廢棄了,建議你不要試著通過 自定義驅(qū)動 來重新實現(xiàn)它。
文件驅(qū)動利用你的文件系統(tǒng)來存儲 session 數(shù)據(jù)。
可以說,文件驅(qū)動和 PHP 自帶的默認 session 實現(xiàn)非常類似,但是有一個很重要的細節(jié)要注意的是, 實際上它們的代碼并不相同,而且有一些局限性(以及優(yōu)勢)。
說的更具體點,它不支持 PHP 的 session.save_path 參數(shù)的 目錄分級(directory level)和 mode 格式 , 另外為了安全性大多數(shù)的參數(shù)都被硬編碼。只提供了 $config['sess_save_path'] 參數(shù)用于設置絕對路徑。
另一個很重要的事情是,確保存儲 session 文件的目錄不能被公開訪問到或者是共享目錄,確保 只有你 能訪問并查看配置的 sess_save_path 目錄中的內(nèi)容。否則,如果任何人都能訪問, 他們就可以從中竊取到當前的 session (這也被稱為 session 固定(session fixation)攻擊)
在類 UNIX 操作系統(tǒng)中,這可以通過在該目錄上執(zhí)行 chmod 命令,將權(quán)限設置為 0700 來實現(xiàn), 這樣就可以只允許目錄的所有者執(zhí)行讀取和寫入操作。但是要注意的是,腳本的執(zhí)行者通常不是你自己, 而是類似于 'www-data' 這樣的用戶,所以只設置權(quán)限可能會破壞你的程序。
根據(jù)你的環(huán)境,你應該像下面這樣來操作。
mkdir /<path to your application directory>/sessions/
chmod 0700 /<path to your application directory>/sessions/
chown www-data /<path to your application directory>/sessions/
有些人可能會選擇使用其他的 session 驅(qū)動,他們認為文件存儲通常比較慢。其實這并不總是對的。
執(zhí)行一些簡單的測試可能會讓你真的相信 SQL 數(shù)據(jù)庫更快一點,但是在 99% 的情況下,這只是當你的 session 并發(fā)非常少的時候是對的。當 session 的并發(fā)數(shù)越來越大,服務器的負載越來越高, 這時就不一樣了,文件系統(tǒng)將會勝過幾乎所有的關系型數(shù)據(jù)庫。
另外,如果性能是你唯一關心的,你可以看下 tmpfs (注意:外部資源),它可以讓你的 session 非???。
數(shù)據(jù)庫驅(qū)動使用諸如 MySQL 或 PostgreSQL 這樣的關系型數(shù)據(jù)庫來存儲 session , 這是一個非常常見的選擇,因為它可以讓開發(fā)者非常方便的訪問應用中的 session 數(shù)據(jù), 因為它只是你的數(shù)據(jù)庫中的一個表而已。
但是,還是有幾點要求必須滿足:
- 只有設置為 default 的數(shù)據(jù)庫連接可以使用(或者在控制器中使用 $this->db 來訪問的連接)
- 你必須啟用 查詢構(gòu)造器
- 不能使用持久連接
- 使用的數(shù)據(jù)庫連接不能啟用 cache_on 參數(shù)
為了使用數(shù)據(jù)庫驅(qū)動,你還需要創(chuàng)建一個我們剛剛已經(jīng)提到的數(shù)據(jù)表,然后將 $config['sess_save_path'] 參數(shù)設置為表名。例如,如果你想使用 'ci_sessions' 這個表名,你可以這樣:
$config['sess_driver'] = 'database';
$config['sess_save_path'] = 'ci_sessions';
注解
如果你從 CodeIgniter 之前的版本中升級過來的,并且沒有配置 'sess_save_path' 參數(shù), Session 類將查找并使用老的 'sess_table_name' 參數(shù)替代。請不要依賴這個行為, 因為它可能會在以后的版本中移除。
然后,新建數(shù)據(jù)表 。
對于 MySQL:
CREATE TABLE IF NOT EXISTS `ci_sessions` (
`id` varchar(40) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`timestamp` int(10) unsigned DEFAULT 0 NOT NULL,
`data` blob NOT NULL,
PRIMARY KEY (id),
KEY `ci_sessions_timestamp` (`timestamp`)
);
對于 PostgreSQL:
CREATE TABLE "ci_sessions" (
"id" varchar(40) NOT NULL,
"ip_address" varchar(45) NOT NULL,
"timestamp" bigint DEFAULT 0 NOT NULL,
"data" text DEFAULT '' NOT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX "ci_sessions_timestamp" ON "ci_sessions" ("timestamp");
如果你想開啟 sess_match_ip 參數(shù),你還應該在新建表之后進行如下操作:
// Works both on MySQL and PostgreSQL
ALTER TABLE ci_sessions ADD CONSTRAINT ci_sessions_id_ip UNIQUE (id, ip_address);
重要
只有 MySQL 和 PostgreSQL 數(shù)據(jù)庫是被正式支持的,因為其他數(shù)據(jù)庫平臺都缺乏合適的鎖機制。 在沒鎖的情況下使用 session 可能會導致大量的問題,特別是使用了大量的 AJAX , 所以我們并不打算支持這種情況。如果你遇到了性能問題,請你在完成 session 數(shù)據(jù)的處理之后, 調(diào)用session_write_close() 方法。
注解
由于 Redis 沒有鎖機制,這個驅(qū)動的鎖是通過一個保持 300 秒的值來模擬的 (emulated by a separate value that is kept for up to 300 seconds)。
Redis 是一種存儲引擎,通常用于緩存,并由于他的高性能而流行起來,這可能也正是你使用 Redis 驅(qū)動的原因。
缺點是它并不像關系型數(shù)據(jù)庫那樣普遍,需要你的系統(tǒng)中安裝了 phpredis 這個 PHP 擴展,它并不是 PHP 程序自帶的。 可能的情況是,你使用 Redis 驅(qū)動的原因是你已經(jīng)非常熟悉 Redis 了并且你使用它還有其他的目的。
和文件驅(qū)動和數(shù)據(jù)庫驅(qū)動一樣,你必須通過 $config['sess_save_path'] 參數(shù)來配置存儲 session 的位置。 這里的格式有些不同,同時也要復雜一點,這在 phpredis 擴展的 README 文件中有很好的解釋,鏈接如下:
https://github.com/phpredis/phpredis#php-session-handler
警告
CodeIgniter 的 Session 類并沒有真的用到 'redis' 的 session.save_handler , 只是 采用了它的路徑的格式而已。
最常見的情況是,一個簡單 host:port 對就可以了:
$config['sess_driver'] = 'redis';
$config['sess_save_path'] = 'tcp://localhost:6379';
注解
由于 Memcache 沒有鎖機制,這個驅(qū)動的鎖是通過一個保持 300 秒的值來模擬的 (emulated by a separate value that is kept for up to 300 seconds)。
Memcached 驅(qū)動和 Redis 驅(qū)動非常相似,除了它的可用性可能要好點,因為 PHP 的 Memcached 擴展已經(jīng)通過 PECL 發(fā)布了,并且在某些 Linux 發(fā)行版本中, 可以非常方便的安裝它。
除了這一點,以及排除任何對 Redis 的偏見,關于 Memcached 要說的真的沒什么區(qū)別, 它也是一款通常用于緩存的產(chǎn)品,而且以它的速度而聞名。
不過,值得注意的是,使用 Memcached 設置 X 的過期時間為 Y 秒,它只能保證 X 會在 Y 秒過后被刪除 (但不會早于這個時間)。這個是非常少見的,但是應該注意一下,因為它可能會導致 session 的丟失。
$config['sess_save_path'] 參數(shù)的格式相當簡單,使用 host:port 對即可:
$config['sess_driver'] = 'memcached';
$config['sess_save_path'] = 'localhost:11211';
也可以使用一個可選的 權(quán)重 參數(shù)來支持多服務器的配置,權(quán)重參數(shù)使用冒號分割(:weight), 但是我們并沒有測試這是絕對可靠的。
如果你想體驗這個特性(風險自負),只需簡單的將多個服務器使用逗號分隔:
// localhost will be given higher priority (5) here,
// compared to 192.0.2.1 with a weight of 1.
$config['sess_save_path'] = 'localhost:11211:5,192.0.2.1:11211:1';
你也可以創(chuàng)建你自己的自定義 session 驅(qū)動,但是要記住的是,這通常來說都不是那么簡單, 因為需要用到很多知識來正確實現(xiàn)它。
你不僅要知道 session 一般的工作原理,而且要知道它在 PHP 中是如何實現(xiàn)的, 還要知道它的內(nèi)部存儲機制是如何工作的,如何去處理并發(fā),如何去避免死鎖(不是通過去掉鎖機制), 以及最后一點但也是很重要的一點,如何去處理潛在的安全問題。
總的來說,如果你不知道怎么在原生的 PHP 中實現(xiàn)這些,那么你也不應該在 CodeIgniter 中嘗試實現(xiàn)它。 我已經(jīng)警告過你了。
如果你只想給你的 session 添加一些額外的功能,你只要擴展 Session 基類就可以了,這要容易的多。 要學習如何實現(xiàn)這點,請閱讀 創(chuàng)建你的類庫 這一節(jié)。
言歸正傳,當你為 CodeIgniter 創(chuàng)建 session 驅(qū)動時,有三條規(guī)則你必須遵循:
將你的驅(qū)動文件放在 application/libraries/Session/drivers/ 目錄下,并遵循 Session 類所使用的命名規(guī)范。
例如,如果你想創(chuàng)建一個名為 'dummy' 的驅(qū)動,那么你需要創(chuàng)建一個名為 Session_dummy_driver 的類, 并將其放在application/libraries/Session/drivers/Session_dummy_driver.php 文件中。
擴展 CI_Session_driver 類。
這只是一個擁有幾個內(nèi)部輔助方法的基本類,同樣可以和其他類庫一樣被擴展。如果你真的需要這樣做, 我們并不打算在這里多做解釋,因為如果你知道如何在 CI 中擴展或覆寫類,那么你已經(jīng)知道這樣做的方法了。 如果你還不知道,那么可能你根本就不應該這樣做。
實現(xiàn) SessionHandlerInterface 接口。
注解
你可能已經(jīng)注意到 SessionHandlerInterface 接口已經(jīng)在 PHP 5.4.0 之后的版本中提供了。 CodeIgniter 會在你運行老版本的 PHP 時自動聲明這個接口。
參考連接中的內(nèi)容,了解為什么以及如何實現(xiàn)。
所以,使用我們上面的 'dummy' 驅(qū)動的例子,你可能會寫如下代碼:
// application/libraries/Session/drivers/Session_dummy_driver.php:
class CI_Session_dummy_driver extends CI_Session_driver implements SessionHandlerInterface
{
public function __construct(&$params)
{
// DO NOT forget this
parent::__construct($params);
// Configuration & other initializations
}
public function open($save_path, $name)
{
// Initialize storage mechanism (connection)
}
public function read($session_id)
{
// Read session data (if exists), acquire locks
}
public function write($session_id, $session_data)
{
// Create / update session data (it might not exist!)
}
public function close()
{
// Free locks, close connections / streams / etc.
}
public function destroy($session_id)
{
// Call close() method & destroy data for current session (order may differ)
}
public function gc($maxlifetime)
{
// Erase data for expired sessions
}
}
如果一切順利,現(xiàn)在你就可以將 sess_driver 參數(shù)設置為 'dummy' ,來使用你自定義的驅(qū)動。恭喜你!
classCI_Session
userdata([$key = NULL])
參數(shù):
返回: Value of the specified item key, or an array of all userdata
返回類型: mixed
從 $_SESSION 數(shù)組中獲取指定的項。如果沒有指定參數(shù),返回所有 "userdata" 的數(shù)組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用 $_SESSION 替代它。
all_userdata()
返回: An array of all userdata
返回類型: array
返回所有 "userdata" 的數(shù)組。
注解
該方法已廢棄,使用不帶參數(shù)的 userdata() 方法來代替。
&get_userdata()
返回: A reference to $_SESSION
返回類型: array
返回一個 $_SESSION 數(shù)組的引用。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
has_userdata($key)
參數(shù):
返回: TRUE if the specified key exists, FALSE if not
返回類型: bool
檢查 $_SESSION 數(shù)組中是否存在某項。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是 isset($_SESSION[$key]) 的一個別名,請使用這個來替代它。
set_userdata($data[, $value = NULL])
參數(shù):
返回類型: void
將數(shù)據(jù)賦值給 $_SESSION 全局變量。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
unset_userdata($key)
參數(shù):
返回類型: void
從 $_SESSION 全局變量中刪除某個值。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是 unset($_SESSION[$key]) 的一個別名,請使用這個來替代它。
mark_as_flash($key)
參數(shù):
返回: TRUE on success, FALSE on failure
返回類型: bool
將 $_SESSION 數(shù)組中的一項(或多項)標記為 "flashdata" 。
get_flash_keys()
返回: Array containing the keys of all "flashdata" items.
返回類型: array
獲取 $_SESSION 數(shù)組中所有標記為 "flashdata" 的一個列表。
umark_flash($key)
參數(shù):
返回類型: void
將 $_SESSION 數(shù)組中的一項(或多項)移除 "flashdata" 標記。
flashdata([$key = NULL])
參數(shù):
返回: Value of the specified item key, or an array of all flashdata
返回類型: mixed
從 $_SESSION 數(shù)組中獲取某個標記為 "flashdata" 的指定項。 如果沒有指定參數(shù),返回所有 "flashdata" 的數(shù)組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用 $_SESSION 替代它。
keep_flashdata($key)
參數(shù):
返回: TRUE on success, FALSE on failure
返回類型: bool
將某個指定的 "flashdata" 設置為在下一次請求中仍然保持有效。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是 mark_as_flash() 方法的一個別名。
set_flashdata($data[, $value = NULL])
參數(shù):
返回類型: void
將數(shù)據(jù)賦值給 $_SESSION 全局變量,并標記為 "flashdata" 。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
mark_as_temp($key[, $ttl = 300])
參數(shù):
返回: TRUE on success, FALSE on failure
返回類型: bool
將 $_SESSION 數(shù)組中的一項(或多項)標記為 "tempdata" 。
get_temp_keys()
返回: Array containing the keys of all "tempdata" items.
返回類型: array
獲取 $_SESSION 數(shù)組中所有標記為 "tempdata" 的一個列表。
umark_temp($key)
參數(shù):
返回類型: void
將 $_SESSION 數(shù)組中的一項(或多項)移除 "tempdata" 標記。
tempdata([$key = NULL])
參數(shù):
返回: Value of the specified item key, or an array of all tempdata
返回類型: mixed
從 $_SESSION 數(shù)組中獲取某個標記為 "tempdata" 的指定項。 如果沒有指定參數(shù),返回所有 "tempdata" 的數(shù)組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用 $_SESSION 替代它。
set_tempdata($data[, $value = NULL])
參數(shù):
返回類型: void
將數(shù)據(jù)賦值給 $_SESSION 全局變量,并標記為 "tempdata" 。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
sess_regenerate([$destroy = FALSE])
參數(shù):
返回類型: void
重新生成 session ID ,$destroy 參數(shù)可選,用于銷毀當前的 session 數(shù)據(jù)。
注解
該方法只是 PHP 原生的 session_regenerate_id() 函數(shù)的一個別名而已。
sess_destroy()
返回類型: void
銷毀當前 session 。
注解
這個方法必須在處理 session 相關的操作的最后調(diào)用。 如果調(diào)用這個方法,所有的 session 數(shù)據(jù)都會丟失。
注解
該方法只是 PHP 原生的 session_destroy() 函數(shù)的一個別名而已。
__get($key)
參數(shù):
返回: The requested session data item, or NULL if it doesn't exist
返回類型: mixed
魔術(shù)方法,根據(jù)你的喜好,使用 $this->session->item 這種方式來替代 $_SESSION['item'] 。
如果你訪問 $this->session->session_id 它也會調(diào)用 session_id() 方法來返回 session ID 。
__set($key, $value)
參數(shù):
返回: void
魔術(shù)方法,直接賦值給 $this->session 屬性,以此來替代賦值給 $_SESSION 數(shù)組:
$this->session->foo = 'bar';
// Results in:
// $_SESSION['foo'] = 'bar';
更多建議: