# Session 類
Session(會話)類可以讓你保持一個用戶的 "狀態" ,并跟蹤他在瀏覽你的網站時的活動。
CodeIgniter 自帶了幾個存儲 session 的驅動:
* 文件(默認的,基于文件系統)
* 數據庫
* Redis
* Memcached
另外,你也可以基于其他的存儲機制來創建你自己的自定義 session 存儲驅動, 使用自定義的驅動,同樣也可以使用 Session 類提供的那些功能。
[TOC=2.3]
## 使用 Session 類
### 初始化 Session 類
Session 通常會在每個頁面載入的時候全局運行,所以 Session 類必須首先被初始化。 您可以在?[控制器](http://codeigniter.org.cn/user_guide/general/controllers.html)?的構造函數中初始化它, 也可以在系統中?[自動加載](http://codeigniter.org.cn/user_guide/general/autoloader.html)。Session 類基本上都是在后臺運行, 你不會注意到。所以當初始化 session 之后,系統會自動讀取、創建和更新 session 數據 。
要手動初始化 Session 類,你可以在控制器的構造函數中使用?$this->load->library()?方法:
~~~
$this->load->library('session');
~~~
初始化之后,就可以使用下面的方法來訪問 Session 對象了:
~~~
$this->session
~~~
重要
由于?[加載類](http://codeigniter.org.cn/user_guide/libraries/loader.html)?是在 CodeIgniter 的控制器基類中實例化的, 所以如果要在你的控制器構造函數中加載類庫的話,確保先調用?parent::__construct()方法。
### Session 是如何工作的?
當頁面載入后,Session 類就會檢查用戶的 cookie 中是否存在有效的 session 數據。 如果 session 數據不存在(或者與服務端不匹配,或者已經過期), 那么就會創建一個新的 session 并保存起來。
如果 session 數據存在并且有效,那么就會更新 session 的信息。 根據你的配置,每一次更新都會生成一個新的 Session ID 。
有一點非常重要,你需要了解一下,Session 類一旦被初始化,它就會自動運行。 上面所說的那些,你完全不用做任何操作。正如接下來你將看到的那樣, 你可以正常的使用 session 數據,至于讀、寫和更新 session 的操作都是自動完成的。
注解
在 CLI 模式下,Session 類將自動關閉,這種做法完全是基于 HTTP 協議的。
#### 關于并發的注意事項
如果你開發的網站并不是大量的使用 AJAX 技術,那么你可以跳過這一節。 如果你的網站是大量的使用了 AJAX,并且遇到了性能問題,那么下面的注意事項, 可能正是你需要的。
在 CodeIgniter 之前的版本中,Session 類并沒有實現鎖機制,這也就意味著, 兩個 HTTP 請求可能會同時使用同一個 session 。說的更專業點就是, 請求是非阻塞的。(requests were non-blocking)
在處理 session 時使用非阻塞的請求同樣意味著不安全,因為在一個請求中修改 session 數據(或重新生成 Session ID)會對并發的第二個請求造成影響。這是導致很多問題的根源, 同時也是為什么 CodeIgniter 3.0 對 Session 類完全重寫的原因。
那么為什么要告訴你這些呢?這是因為在你查找性能問題的原因時, 可能會發現加鎖機制正是導致性能問題的罪魁禍首,因此就想著如何去掉鎖 ...
**請不要這樣做!**?去掉加鎖機制是完全錯誤的,它會給你帶來更多的問題!
鎖并不是問題,它是一種解決方案。你的問題是當 session 已經處理完畢不再需要時, 你還將 session 保持是打開的狀態。所以,你需要做的其實是,當結束當前請求時, 將不再需要的 session 關閉掉。
簡單來說就是:當你不再需要使用某個 session 變量時,就使用?session_write_close()?方法來關閉它。
### 什么是 Session 數據?
Session 數據是個簡單的數組,帶有一個特定的 session ID (cookie)。
如果你之前在 PHP 里使用過 session ,你應該對 PHP 的?[$_SESSION 全局變量](http://php.net/manual/en/reserved.variables.session.php)?很熟悉(如果沒有,請閱讀下鏈接中的內容)。
CodeIgniter 使用了相同的方式來訪問 session 數據,同時使用了 PHP 自帶的 session 處理機制, 使用 session 數據和操作?$_SESSION?數組一樣簡單(包括讀取,設置,取消設置)。
另外,CodeIgniter 還提供了兩種特殊類型的 session 數據:flashdata 和 tempdata ,在下面將有介紹。
注解
在之前的 CodeIgniter 版本中,常規的 session 數據被稱之為 'userdata' ,當文檔中出現這個詞時請記住這一點。 大部分都是用于解釋自定義 'userdata' 方法是如何工作的。
### 獲取 Session 數據
session 數組中的任何信息都可以通過?$_SESSION?全局變量獲取:
~~~
$_SESSION['item']
~~~
或使用下面的方法(magic getter):
~~~
$this->session->item
~~~
同時,為了和之前的版本兼容,也可以使用?userdata()?方法:
~~~
$this->session->userdata('item');
~~~
其中,item 是你想獲取的數組的鍵值。例如,將 'name' 鍵值對應的項賦值給?$name?變量, 你可以這樣:
~~~
$name = $_SESSION['name'];
// or:
$name = $this->session->name
// or:
$name = $this->session->userdata('name');
~~~
注解
如果你訪問的項不存在,userdata()?方法返回 NULL 。
如果你想獲取所有已存在的 userdata ,你可以忽略 item 參數:
~~~
$_SESSION
// or:
$this->session->userdata();
~~~
### 添加 Session 數據
假設某個用戶訪問你的網站,當他完成認證之后,你可以將他的用戶名和 email 地址添加到 session 中, 這樣當你需要的時候你就可以直接訪問這些數據,而無法查詢數據庫了。
你可以簡單的將數據賦值給?$_SESSION?數組,或賦值給?$this->session?的某個屬性。
同時,老版本中的通過 "userdata" 來賦值的方法也還可以用,只不過是需要傳遞一個包含你的數據的數組 給?set_userdata()?方法:
~~~
$this->session->set_userdata($array);
~~~
其中,$array?是包含新增數據的一個關聯數組,下面是個例子:
~~~
$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');
~~~
### 刪除 Session 數據
和其他的變量一樣,可以使用?unset()?方法來刪除?$_SESSION?數組中的某個值:
~~~
unset($_SESSION['some_name']);
// or multiple values:
unset(
$_SESSION['some_name'],
$_SESSION['another_name']
);
~~~
同時,正如?set_userdata()?方法可用于向 session 中添加數據,unset_userdata()?方法可用于刪除指定鍵值的數據。例如,如果你想從你的 session 數組中刪除 'some_name':
~~~
$this->session->unset_userdata('some_name');
~~~
這個方法也可以使用一個數組來同時刪除多個值:
~~~
$array_items = array('username', 'email');
$this->session->unset_userdata($array_items);
~~~
注解
在 CodeIgniter 之前的版本中,unset_userdata()?方法接受一個關聯數組, 包含?key?=>?'dummy?value'?這樣的鍵值對,這種方式不再支持。
### Flashdata
CodeIgniter 支持 "flashdata" ,它指的是一種只對下一次請求有效的 session 數據, 之后將會自動被清除。
這用于一次性的信息時特別有用,例如錯誤或狀態信息(諸如 "第二條記錄刪除成功" 這樣的信息)。
要注意的是,flashdata 就是常規的 session 變量,只不過以特殊的方式保存在 '__ci_vars' 鍵下 (警告:請不要亂動這個值)。
將已有的值標記為 "flashdata":
~~~
$this->session->mark_as_flash('item');
~~~
通過傳一個數組,同時標記多個值為 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');
~~~
你還可以傳一個數組給?set_flashdata()?方法,和?set_userdata()?方法一樣。
讀取 flashdata 和讀取常規的 session 數據一樣,通過?$_SESSION?數組:
~~~
$_SESSION['item']
~~~
重要
userdata()?方法不會返回 flashdata 數據。
如果你要確保你讀取的就是 "flashdata" 數據,而不是其他類型的數據,可以使用?flashdata()?方法:
~~~
$this->session->flashdata('item');
~~~
或者不傳參數,直接返回所有的 flashdata 數組:
~~~
$this->session->flashdata();
~~~
注解
如果讀取的值不存在,flashdata()?方法返回 NULL 。
如果你需要在另一個請求中還繼續保持 flashdata 變量,你可以使用?keep_flashdata()?方法。 可以傳一個值,或包含多個值的一個數組。
~~~
$this->session->keep_flashdata('item');
$this->session->keep_flashdata(array('item1', 'item2', 'item3'));
~~~
### Tempdata
CodeIgniter 還支持 "tempdata" ,它指的是一種帶有有效時間的 session 數據, 當它的有效時間已過期,或在有效時間內被刪除,都會自動被清除。
和 flashdata 一樣, tempdata 也是常規的 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);
~~~
你還可以傳一個數組給?set_tempdata()?方法:
~~~
$tempdata = array('newuser' => TRUE, 'message' => 'Thanks for joining!');
$this->session->set_tempdata($tempdata, NULL, $expire);
~~~
注解
如果沒有設置 expiration 參數,或者設置為 0 ,將默認使用 300秒(5分鐘)作為生存時間(time-to-live)。
要讀取 tempdata 數據,你可以再一次通過?$_SESSION?數組:
~~~
$_SESSION['item']
~~~
重要
userdata()?方法不會返回 tempdata 數據。
如果你要確保你讀取的就是 "tempdata" 數據,而不是其他類型的數據,可以使用?tempdata()?方法:
~~~
$this->session->tempdata('item');
~~~
或者不傳參數,直接返回所有的 tempdata 數組:
~~~
$this->session->tempdata();
~~~
注解
如果讀取的值不存在,tempdata()?方法返回 NULL 。
如果你需要在某個 tempdata 過期之前刪除它,你可以直接通過?$_SESSION?數組來刪除:
~~~
unset($_SESSION['item']);
~~~
但是,這不會刪除這個值的 tempdata 標記(會在下一次 HTTP 請求時失效),所以, 如果你打算在相同的請求中重用這個值,你可以使用unset_tempdata():
~~~
$this->session->unset_tempdata('item');
~~~
### 銷毀 Session
要清除當前的 session(例如:退出登錄時),你可以簡單的使用 PHP 自帶的?[session_destroy()](http://php.net/session_destroy)?函數或者?sess_destroy()?方法。 兩種方式效果完全一樣:
~~~
session_destroy();
// or
$this->session->sess_destroy();
~~~
注解
這必須是同一個請求中關于 session 的最后一次操作,所有的 session 數據(包括 flashdata 和 tempdata)都被永久性銷毀,銷毀之后,關于 session 的方法將不可用。
### 訪問 session 元數據
在之前的 CodeIgniter 版本中,session 數據默認包含 4 項:'session_id' 、 'ip_address' 、 'user_agent' 、 'last_activity' 。
這是由 session 具體的工作方式決定的,但是我們現在的實現沒必要這樣做了。 盡管如此,你的應用程序可能還依賴于這些值,所以下面提供了訪問這些值的替代方法:
>
>
> * session_id:?session_id()
> * ip_address:?$_SERVER['REMOTE_ADDR']
> * user_agent:?$this->input->user_agent()?(unused by sessions)
> * last_activity: 取決于 session 的存儲方式,沒有直接的方法,抱歉!
>
>
### Session 參數
在 CodeIgniter 中通常所有的東西都是拿來直接就可以用的,盡管如此,session 對于所有的程序來說, 都是一個非常敏感的部分,所以必須要小心的配置它。請花點時間研究下下面所有的選項以及每個選項的作用。
你可以在你的配置文件?**application/config/config.php**?中找到下面的關于 session 的配置參數:
| 參數 | 默認值 | 選項 | 描述 |
| --- | --- | --- | --- |
| **sess_driver** | files | files/database/redis/memcached/custom | 使用的存儲 session 的驅動 |
| **sess_cookie_name** | ci_session | [A-Za-z_-] characters only | session cookie 的名稱 |
| **sess_expiration** | 7200 (2 hours) | Time in seconds (integer) | 你希望 session 持續的秒數 如果你希望 session 不過期(直到瀏覽器關閉),將其設置為 0 |
| **sess_save_path** | NULL | None | 指定存儲位置,取決于使用的存儲 session 的驅動 |
| **sess_match_ip** | FALSE | TRUE/FALSE (boolean) | 讀取 session cookie 時,是否驗證用戶的 IP 地址 注意有些 ISP 會動態的修改 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 對應的數據 如果設置為 FALSE ,數據之后將自動被垃圾回收器刪除 |
注解
如果上面的某個參數沒有配置,Session 類將會試圖讀取 php.ini 配置文件中的 session 相關的配置 (例如 'sess_expire_on_close')。但是,請不要依賴于這個行為,因為這可能會導致不可預期的結果,而且 這也有可能在未來的版本中修改。請合理的配置每一個參數。
除了上面的這些參數之外,cookie 和 session 原生的驅動還會公用下面這些 由?[輸入類](http://codeigniter.org.cn/user_guide/libraries/input.html)?和?[安全類](http://codeigniter.org.cn/user_guide/libraries/security.html)?提供的配置參數。
| 參數 | 默認值 | 描述 |
| --- | --- | --- |
| **cookie_domain** | '' | session 可用的域 |
| **cookie_path** | / | session 可用的路徑 |
| **cookie_secure** | FALSE | 是否只在加密連接(HTTPS)時創建 session cookie |
注解
'cookie_httponly' 配置對 session 沒有影響。出于安全原因,HttpOnly 參數將一直啟用。 另外,'cookie_prefix' 參數完全可以忽略。
### Session 驅動
正如上面提到的,Session 類自帶了 4 種不同的驅動(或叫做存儲引擎)可供使用:
>
>
> * files
> * database
> * redis
> * memcached
>
>
默認情況下,初始化 session 時將使用?[文件驅動](http://codeigniter.org.cn/user_guide/libraries/sessions.html#id14)?,因為這是最安全的選擇,可以在所有地方按預期工作 (幾乎所有的環境下都有文件系統)。
但是,你也可以通過?**application/config/config.php**?配置文件中的?$config['sess_driver']?參數來使用任何其他的驅動。特別提醒的是,每一種驅動都有它自己的注意事項,所以在你選擇之前, 確定你熟悉它們。
另外,如果默認提供的這些不能滿足你的需求,你也可以創建和使用?[自定義驅動](http://codeigniter.org.cn/user_guide/libraries/sessions.html#id19)?。
注解
在之前版本的 CodeIgniter 中,只有 "cookie 驅動" 這唯一的一種選擇, 因為這個我們收到了大量的負面的反饋。因此,我們吸取了社區的反饋意見,同時也要提醒你, 因為它**不安全**,所以已經被廢棄了,建議你不要試著通過 自定義驅動 來重新實現它。
#### 文件驅動
文件驅動利用你的文件系統來存儲 session 數據。
可以說,文件驅動和 PHP 自帶的默認 session 實現非常類似,但是有一個很重要的細節要注意的是, 實際上它們的代碼并不相同,而且有一些局限性(以及優勢)。
說的更具體點,它不支持 PHP 的?[session.save_path 參數的 目錄分級(directory level)和 mode 格式](http://php.net/manual/en/session.configuration.php#ini.session.save-path)?, 另外為了安全性大多數的參數都被硬編碼。只提供了?$config['sess_save_path']?參數用于設置絕對路徑。
另一個很重要的事情是,確保存儲 session 文件的目錄不能被公開訪問到或者是共享目錄,確保?**只有你**?能訪問并查看配置的?sess_save_path?目錄中的內容。否則,如果任何人都能訪問, 他們就可以從中竊取到當前的 session (這也被稱為 session 固定(session fixation)攻擊)
在類 UNIX 操作系統中,這可以通過在該目錄上執行?chmod?命令,將權限設置為 0700 來實現, 這樣就可以只允許目錄的所有者執行讀取和寫入操作。但是要注意的是,腳本的執行者通常不是你自己, 而是類似于 'www-data' 這樣的用戶,所以只設置權限可能會破壞你的程序。
根據你的環境,你應該像下面這樣來操作。
~~~
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 驅動,他們認為文件存儲通常比較慢。其實這并不總是對的。
執行一些簡單的測試可能會讓你真的相信 SQL 數據庫更快一點,但是在 99% 的情況下,這只是當你的 session 并發非常少的時候是對的。當 session 的并發數越來越大,服務器的負載越來越高, 這時就不一樣了,文件系統將會勝過幾乎所有的關系型數據庫。
另外,如果性能是你唯一關心的,你可以看下?[tmpfs](http://eddmann.com/posts/storing-php-sessions-file-caches-in-memory-using-tmpfs/)?(注意:外部資源),它可以讓你的 session 非常快。
#### 數據庫驅動
數據庫驅動使用諸如 MySQL 或 PostgreSQL 這樣的關系型數據庫來存儲 session , 這是一個非常常見的選擇,因為它可以讓開發者非常方便的訪問應用中的 session 數據, 因為它只是你的數據庫中的一個表而已。
但是,還是有幾點要求必須滿足:
>
>
> * 只有設置為?**default**?的數據庫連接可以使用(或者在控制器中使用?$this->db?來訪問的連接)
> * 你必須啟用?[查詢構造器](http://codeigniter.org.cn/user_guide/database/query_builder.html)
> * 不能使用持久連接
> * 使用的數據庫連接不能啟用?cache_on?參數
>
>
為了使用數據庫驅動,你還需要創建一個我們剛剛已經提到的數據表,然后將?$config['sess_save_path']?參數設置為表名。例如,如果你想使用 'ci_sessions' 這個表名,你可以這樣:
~~~
$config['sess_driver'] = 'database';
$config['sess_save_path'] = 'ci_sessions';
~~~
注解
如果你從 CodeIgniter 之前的版本中升級過來的,并且沒有配置 'sess_save_path' 參數, Session 類將查找并使用老的 'sess_table_name' 參數替代。請不要依賴這個行為, 因為它可能會在以后的版本中移除。
然后,新建數據表 。
對于 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?參數,你還應該在新建表之后進行如下操作:
~~~
// Works both on MySQL and PostgreSQL
ALTER TABLE ci_sessions ADD CONSTRAINT ci_sessions_id_ip UNIQUE (id, ip_address);
~~~
重要
只有 MySQL 和 PostgreSQL 數據庫是被正式支持的,因為其他數據庫平臺都缺乏合適的鎖機制。 在沒鎖的情況下使用 session 可能會導致大量的問題,特別是使用了大量的 AJAX , 所以我們并不打算支持這種情況。如果你遇到了性能問題,請你在完成 session 數據的處理之后, 調用session_write_close()?方法。
#### Redis 驅動
注解
由于 Redis 沒有鎖機制,這個驅動的鎖是通過一個保持 300 秒的值來模擬的 (emulated by a separate value that is kept for up to 300 seconds)。
Redis 是一種存儲引擎,通常用于緩存,并由于他的高性能而流行起來,這可能也正是你使用 Redis 驅動的原因。
缺點是它并不像關系型數據庫那樣普遍,需要你的系統中安裝了?[phpredis](https://github.com/phpredis/phpredis)?這個 PHP 擴展,它并不是 PHP 程序自帶的。 可能的情況是,你使用 Redis 驅動的原因是你已經非常熟悉 Redis 了并且你使用它還有其他的目的。
和文件驅動和數據庫驅動一樣,你必須通過?$config['sess_save_path']?參數來配置存儲 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';
~~~
#### Memcached 驅動
注解
由于 Memcache 沒有鎖機制,這個驅動的鎖是通過一個保持 300 秒的值來模擬的 (emulated by a separate value that is kept for up to 300 seconds)。
Memcached 驅動和 Redis 驅動非常相似,除了它的可用性可能要好點,因為 PHP 的?[Memcached](http://php.net/memcached)?擴展已經通過 PECL 發布了,并且在某些 Linux 發行版本中, 可以非常方便的安裝它。
除了這一點,以及排除任何對 Redis 的偏見,關于 Memcached 要說的真的沒什么區別, 它也是一款通常用于緩存的產品,而且以它的速度而聞名。
不過,值得注意的是,使用 Memcached 設置 X 的過期時間為 Y 秒,它只能保證 X 會在 Y 秒過后被刪除 (但不會早于這個時間)。這個是非常少見的,但是應該注意一下,因為它可能會導致 session 的丟失。
$config['sess_save_path']?參數的格式相當簡單,使用?host:port?對即可:
~~~
$config['sess_driver'] = 'memcached';
$config['sess_save_path'] = 'localhost:11211';
~~~
##### 小提示
也可以使用一個可選的?權重?參數來支持多服務器的配置,權重參數使用冒號分割(: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';
~~~
#### 自定義驅動
你也可以創建你自己的自定義 session 驅動,但是要記住的是,這通常來說都不是那么簡單, 因為需要用到很多知識來正確實現它。
你不僅要知道 session 一般的工作原理,而且要知道它在 PHP 中是如何實現的, 還要知道它的內部存儲機制是如何工作的,如何去處理并發,如何去避免死鎖(不是通過去掉鎖機制), 以及最后一點但也是很重要的一點,如何去處理潛在的安全問題。
總的來說,如果你不知道怎么在原生的 PHP 中實現這些,那么你也不應該在 CodeIgniter 中嘗試實現它。 我已經警告過你了。
如果你只想給你的 session 添加一些額外的功能,你只要擴展 Session 基類就可以了,這要容易的多。 要學習如何實現這點,請閱讀?[創建你的類庫](http://codeigniter.org.cn/user_guide/general/creating_libraries.html)?這一節。
言歸正傳,當你為 CodeIgniter 創建 session 驅動時,有三條規則你必須遵循:
>
>
> * 將你的驅動文件放在?**application/libraries/Session/drivers/**?目錄下,并遵循 Session 類所使用的命名規范。
>
>
>
> 例如,如果你想創建一個名為 'dummy' 的驅動,那么你需要創建一個名為?Session_dummy_driver?的類, 并將其放在application/libraries/Session/drivers/Session_dummy_driver.php?文件中。
>
>
> * 擴展?CI_Session_driver?類。
>
>
>
> 這只是一個擁有幾個內部輔助方法的基本類,同樣可以和其他類庫一樣被擴展。如果你真的需要這樣做, 我們并不打算在這里多做解釋,因為如果你知道如何在 CI 中擴展或覆寫類,那么你已經知道這樣做的方法了。 如果你還不知道,那么可能你根本就不應該這樣做。
>
>
> * 實現?[SessionHandlerInterface](http://php.net/sessionhandlerinterface)?接口。
>
>
>
>
>
> 注解
>
>
>
> 你可能已經注意到?SessionHandlerInterface?接口已經在 PHP 5.4.0 之后的版本中提供了。 CodeIgniter 會在你運行老版本的 PHP 時自動聲明這個接口。
>
>
>
>
>
> 參考連接中的內容,了解為什么以及如何實現。
>
>
>
>
所以,使用我們上面的 'dummy' 驅動的例子,你可能會寫如下代碼:
~~~
// 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
}
}
~~~
如果一切順利,現在你就可以將?sess_driver?參數設置為 'dummy' ,來使用你自定義的驅動。恭喜你!
## 類參考
classCI_Session
userdata([$key = NULL])
參數:
* **$key**?(mixed) -- Session item key or NULL
返回: Value of the specified item key, or an array of all userdata
返回類型: mixed
從?$_SESSION?數組中獲取指定的項。如果沒有指定參數,返回所有 "userdata" 的數組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用?$_SESSION?替代它。
all_userdata()
返回: An array of all userdata
返回類型: array
返回所有 "userdata" 的數組。
注解
該方法已廢棄,使用不帶參數的?userdata()?方法來代替。
&get_userdata()
返回: A reference to?$_SESSION
返回類型: array
返回一個?$_SESSION?數組的引用。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
has_userdata($key)
參數:
* **$key**?(string) -- Session item key
返回: TRUE if the specified key exists, FALSE if not
返回類型: bool
檢查?$_SESSION?數組中是否存在某項。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是?isset($_SESSION[$key])?的一個別名,請使用這個來替代它。
set_userdata($data[,?$value = NULL])
參數:
* **$data**?(mixed) -- An array of key/value pairs to set as session data, or the key for a single item
* **$value**?(mixed) -- The value to set for a specific session item, if $data is a key
返回類型: void
將數據賦值給?$_SESSION?全局變量。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
unset_userdata($key)
參數:
* **$key**?(mixed) -- Key for the session data item to unset, or an array of multiple keys
返回類型: void
從?$_SESSION?全局變量中刪除某個值。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是?unset($_SESSION[$key])?的一個別名,請使用這個來替代它。
mark_as_flash($key)
參數:
* **$key**?(mixed) -- Key to mark as flashdata, or an array of multiple keys
返回: TRUE on success, FALSE on failure
返回類型: bool
將?$_SESSION?數組中的一項(或多項)標記為 "flashdata" 。
get_flash_keys()
返回: Array containing the keys of all "flashdata" items.
返回類型: array
獲取?$_SESSION?數組中所有標記為 "flashdata" 的一個列表。
umark_flash($key)
參數:
* **$key**?(mixed) -- Key to be un-marked as flashdata, or an array of multiple keys
返回類型: void
將?$_SESSION?數組中的一項(或多項)移除 "flashdata" 標記。
flashdata([$key = NULL])
參數:
* **$key**?(mixed) -- Flashdata item key or NULL
返回: Value of the specified item key, or an array of all flashdata
返回類型: mixed
從?$_SESSION?數組中獲取某個標記為 "flashdata" 的指定項。 如果沒有指定參數,返回所有 "flashdata" 的數組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用?$_SESSION?替代它。
keep_flashdata($key)
參數:
* **$key**?(mixed) -- Flashdata key to keep, or an array of multiple keys
返回: TRUE on success, FALSE on failure
返回類型: bool
將某個指定的 "flashdata" 設置為在下一次請求中仍然保持有效。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 它只是?mark_as_flash()?方法的一個別名。
set_flashdata($data[,?$value = NULL])
參數:
* **$data**?(mixed) -- An array of key/value pairs to set as flashdata, or the key for a single item
* **$value**?(mixed) -- The value to set for a specific session item, if $data is a key
返回類型: void
將數據賦值給?$_SESSION?全局變量,并標記為 "flashdata" 。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
mark_as_temp($key[,?$ttl = 300])
參數:
* **$key**?(mixed) -- Key to mark as tempdata, or an array of multiple keys
* **$ttl**?(int) -- Time-to-live value for the tempdata, in seconds
返回: TRUE on success, FALSE on failure
返回類型: bool
將?$_SESSION?數組中的一項(或多項)標記為 "tempdata" 。
get_temp_keys()
返回: Array containing the keys of all "tempdata" items.
返回類型: array
獲取?$_SESSION?數組中所有標記為 "tempdata" 的一個列表。
umark_temp($key)
參數:
* **$key**?(mixed) -- Key to be un-marked as tempdata, or an array of multiple keys
返回類型: void
將?$_SESSION?數組中的一項(或多項)移除 "tempdata" 標記。
tempdata([$key = NULL])
參數:
* **$key**?(mixed) -- Tempdata item key or NULL
返回: Value of the specified item key, or an array of all tempdata
返回類型: mixed
從?$_SESSION?數組中獲取某個標記為 "tempdata" 的指定項。 如果沒有指定參數,返回所有 "tempdata" 的數組。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。 你可以直接使用?$_SESSION?替代它。
set_tempdata($data[,?$value = NULL])
參數:
* **$data**?(mixed) -- An array of key/value pairs to set as tempdata, or the key for a single item
* **$value**?(mixed) -- The value to set for a specific session item, if $data is a key
* **$ttl**?(int) -- Time-to-live value for the tempdata item(s), in seconds
返回類型: void
將數據賦值給?$_SESSION?全局變量,并標記為 "tempdata" 。
注解
這是個遺留方法,只是為了和老的應用程序向前兼容而保留。
sess_regenerate([$destroy = FALSE])
參數:
* **$destroy**?(bool) -- Whether to destroy session data
返回類型: void
重新生成 session ID ,$destroy 參數可選,用于銷毀當前的 session 數據。
注解
該方法只是 PHP 原生的?[session_regenerate_id()](http://php.net/session_regenerate_id)?函數的一個別名而已。
sess_destroy()
返回類型: void
銷毀當前 session 。
注解
這個方法必須在處理 session 相關的操作的**最后**調用。 如果調用這個方法,所有的 session 數據都會丟失。
注解
該方法只是 PHP 原生的?[session_destroy()](http://php.net/session_destroy)?函數的一個別名而已。
__get($key)
參數:
* **$key**?(string) -- Session item key
返回: The requested session data item, or NULL if it doesn't exist
返回類型: mixed
魔術方法,根據你的喜好,使用?$this->session->item?這種方式來替代?$_SESSION['item']?。
如果你訪問?$this->session->session_id?它也會調用?session_id()?方法來返回 session ID 。
__set($key,?$value)
參數:
* **$key**?(string) -- Session item key
* **$value**?(mixed) -- Value to assign to the session item key
返回: void
魔術方法,直接賦值給?$this->session?屬性,以此來替代賦值給?$_SESSION?數組:
~~~
$this->session->foo = 'bar';
// Results in:
// $_SESSION['foo'] = 'bar';
~~~
- 歡迎使用 CodeIgniter
- 安裝說明
- 下載 CodeIgniter
- 安裝說明
- 從老版本升級
- 疑難解答
- CodeIgniter 概覽
- CodeIgniter 將從這里開始
- CodeIgniter 是什么?
- 支持特性
- 應用程序流程圖
- 模型-視圖-控制器
- 設計與架構目標
- 教程 - 內容提要
- 加載靜態內容
- 讀取新聞條目
- 創建新聞條目
- 結束語
- 常規主題
- CodeIgniter URL
- 控制器
- 保留名稱
- 視圖
- 模型
- 輔助函數
- 使用 CodeIgniter 類庫
- 創建類庫
- 使用 CodeIgniter 驅動器
- 創建驅動器
- 創建核心系統類
- 創建附屬類
- 鉤子 - 擴展框架核心
- 自動加載資源
- 公共函數
- 兼容性函數
- URI 路由
- 錯誤處理
- 網頁緩存
- 程序分析
- 以 CLI 方式運行
- 管理你的應用程序
- 處理多環境
- 在視圖文件中使用 PHP 替代語法
- 安全
- PHP 開發規范
- 類庫參考
- 基準測試類
- 緩存驅動器
- 日歷類
- 購物車類
- 配置類
- Email 類
- 加密類
- 加密類(新版)
- 文件上傳類
- 表單驗證類
- FTP 類
- 圖像處理類
- 輸入類
- Javascript 類
- 語言類
- 加載器類
- 遷移類
- 輸出類
- 分頁類
- 模板解析類
- 安全類
- Session 類
- HTML 表格類
- 引用通告類
- 排版類
- 單元測試類
- URI 類
- 用戶代理類
- XML-RPC 與 XML-RPC 服務器類
- Zip 編碼類
- 數據庫參考
- 數據庫快速入門: 示例代碼
- 數據庫配置
- 連接你的數據庫
- 查詢
- 生成查詢結果
- 查詢輔助函數
- 查詢構造器類
- 事務
- 數據庫元數據
- 自定義函數調用
- 數據庫緩存類
- 數據庫工廠類
- 數據庫工具類
- 數據庫驅動器參考
- 輔助函數參考
- 數組輔助函數
- 驗證碼輔助函數
- Cookie 輔助函數
- 日期輔助函數
- 目錄輔助函數
- 下載輔助函數
- 郵件輔助函數
- 文件輔助函數
- 表單輔助函數
- HTML 輔助函數
- 語言輔助函數
- Inflector 輔助函數
- 數字輔助函數
- 路徑輔助函數
- 安全輔助函數
- 表情輔助函數
- 字符串輔助函數
- 文本輔助函數
- 排版輔助函數
- URL 輔助函數
- XML 輔助函數
- 向 CodeIgniter 貢獻你的力量