セッションライブラリ¶
The Session class permits you to maintain a user's "state" and track their activity while they browse your site.
CodeIgniter comes with a few session storage drivers, that you can see in the last section of the table of contents:
Using the Session Class¶
Initializing a Session¶
セッションは通常、各ページをまたいでグローバルに実行されます。そのため、セッションクラスはまるで魔法のように初期化される必要があります。
セッションを初期化し、アクセスするには次のようにします:
$session = \Config\Services::session($config);
$config
パラメータはオプションです――あなたのアプリケーションでの設定です。
渡されない場合は、サービスレジスタはデフォルトのもので初期化します。
いちどロードされれば、セッションライブラリオブジェクトは利用可能になります:
$session
別の方法として、ヘルパ関数を使うこともできます。その場合はデフォルト設定が使用されます。このバージョンはすこしだけコードが読みやすくなりますが、設定オプションは使用できなくなります。
$session = session();
セッションはどのように動作しますか?¶
ページが読み込まれると、セッションクラスは有効なセッションクッキーがユーザのブラウザから送信されたかどうかをチェックします。セッションクッキーが存在 しない 場合(またはサーバに保存されているものと一致しないか、 有効期限が切れている場合)、新しいセッションが作成され、保存されます。
有効なセッションが存在する場合、その情報が更新されます。更新するごとにセッション ID を再生成されるように設定することもできます。
重要なこととして、いちど初期化されたら、セッションクラスは自動的に実行されます。その動作をさせるためにあなたが何かをする必要はありません。以降に書かれているように、セッション操作をするにあたり、セッションの読み込み、書き込み、更新のプロセスは自動的に行われます。
注釈
CLI においては、セッションライブラリは自動的に停止します。セッションはもっぱら HTTP プロトコルにもとづく概念だからです。
並行性に関する注意¶
AJAX を多用しているウェブサイトを開発しているわけではないかぎり、このセクションはスキップしてもよいです。しかしながらそうでない場合、さらには パフォーマンスの問題が発生している場合、この注意書きはまさにあなたが探し求めているものでしょう。
CodeIgniter の以前のバージョンのセッションはロックを実装していませんでした。 すなわち、同一のセッションを利用するふたつの HTTP リクエストはまったく同時に実行できていました[訳注: 以前のバージョンとは 2.x 系以前を指します]。より適切な専門用語で言うならば、リクエストは non-blocking でした。
However, non-blocking requests in the context of sessions also means unsafe, because, modifications to session data (or session ID regeneration) in one request can interfere with the execution of a second, concurrent request. このことはいろいろな問題の根っことなり、CodeIgniter 3.0 でセッションライブラリを完全に書き直すおもな理由となりました。
なぜ私たちはわざわざこんなことを言っているのですか?それはこのあとあなたがパフォーマンス問題の原因を見つけ出そうとして、ロックが問題であると断定し、それゆえロックをどうやって外そうかと調べ始めるだろうから……。
そ ん な こ と は し な い で !ロックの削除は 間違っている でしょう、そしてより多くの問題が発生します!
ロックは問題ではなく、それは解決になりません。あなたの問題は、もうすでに処理をし終わってもう不要になったにもかかわらず、ひらいたセッションを持ちっぱなしにしていることです。なので必要なことは、現在のリクエストのためのセッションがもういらなくなったあと、セッションを閉じることです。
$session->destroy();
セッションデータとは何か?¶
セッションデータは、特定のセッション ID (クッキー) に紐付いた単なる配列です。
もし以前から PHP でセッションを利用しているなら、PHP の $_SESSION スーパーグローバル変数 に精通していることでしょう(そうでない場合は、そのリンクのコンテンツをお読みください)。
CodeIgniter はセッションデータへのアクセス方法をそれと同じ手段で提供します。つまり、PHP のセッションハンドラの仕組みを使っています。セッションデータの使い方は $_SESSION
配列を操作 (読み込み、設定および削除) するのと同じくらい簡単です。
加えて、CodeIgniterでは以下に説明されているさらに 2 種類の セッションデータを提供します: flashdata と tempdata です。
セッションデータの取得¶
セッション配列のどんな情報でも、 $_SESSION
スーパーグローバル変数を通して利用できます:
$_SESSION['item']
または従来型のアクセサメソッドを通じて:
$session->get('item');
もしくはマジックメソッドで:
$session->item
はたまたセッションヘルパ関数で:
session('item');
item
の箇所は、取得したい項目に対応する配列のキーです。
たとえば $name
変数に以前に格納した 'name' の項目を割り当てるには、 こうします:
$name = $_SESSION['name'];
// または:
$name = $session->name
// または:
$name = $session->get('name');
注釈
アクセスしようとしている項目が存在しない場合、 get()
メソッドは NULL を返します。
存在するすべてのユーザデータを取得したい場合は、単にキーを省略してください(マジックメソッドは単一のプロパティとしてのみ動作します):
$_SESSION
// または:
$session->get();
セッションデータの追加¶
それでは、あなたのサイトにあるユーザがログインしたとしましょう。認証されると、セッションにユーザー名とメールアドレスを追加することができます。あなたが必要とするときに、データベースクエリを実行することなく取得できるようにするためです。
シンプルに $_SESSION
配列にデータを割り当てることでそれが可能です、ほかの変数と同じようにです。もしくは $session プロパティとして割り当てます。
The former userdata method is deprecated,
but you can pass an array containing your new session data to the
set()
method:
$session->set($array);
``$array``の箇所はあなたの新しいデータを含む連想配列です。次に例を示します:
$newdata = [
'username' => 'johndoe',
'email' => 'johndoe@some-site.com',
'logged_in' => TRUE
];
$session->set($newdata);
If you want to add session data one value at a time, set()
also
supports this syntax:
$session->set('some_name', '何らかの値');
セッション値が存在することを確認したい場合は、単に isset()
でチェックしてください:
// 'some_name' の値が存在しないか NULL の場合は FALSE を、
// そうでなければ TRUE を返します:
isset($_SESSION['some_name'])
もしくは has()
を呼び出します:
$session->has('some_name');
Pushing new value to session data¶
The push method is used to push a new value onto a session value that is an array. For instance, if the 'hobbies' key contains an array of hobbies, you can add a new value onto the array like so:
$session->push('hobbies', ['sport'=>'tennis']);
セッションデータの削除¶
他の変数とまったく同じように、 $_SESSION
の値を削除するには unset()
を使います:
unset($_SESSION['some_name']);
// 複数の値の場合:
unset(
$_SESSION['some_name'],
$_SESSION['another_name']
);
また、 set()
がセッションに値を追加するように、 remove()
に配列のキーを渡すことで値を削除できます。例として、セッションデータ配列から 'some_name' を削除したい場合は:
$session->remove('some_name');
このメソッドは削除したいキーの配列を受けつけます:
$array_items = ['username', 'email'];
$session->remove($array_items);
フラッシュデータ¶
CodeIgniter では "フラッシュデータ" をサポートします。すなわち、次のリクエストのためだけに利用でき、その後自動的にクリアされるセッションデータです。
これは非常に便利で、特に1回だけの情報、エラーまたはステータスメッセージに使えます(たとえば: "レコード2を削除しました")。
フラッシュデータ変数は通常のセッション変数であり、CodeIgniter のセッションハンドラの中で管理されます。
既存のアイテムを "フラッシュデータ" としてマークするには次のようにします:
$session->markAsFlashdata('item');
フラッシュデータとして複数の項目をマークしたい場合は、単に配列としてキーを渡します:
$session->markAsFlashdata(['item', 'item2']);
フラッシュデータを追加するにはこうします:
$_SESSION['item'] = 'value';
$session->markAsFlashdata('item');
または別の方法として、 setFlashdata()
メソッドを使います:
$session->setFlashdata('item', '値');
set()
と同じ方法で setFlashdata()
に配列を渡すこともできます。
フラッシュデータ変数を読み込むには、通常のセッションデータと同じく $_SESSION
を通じて行います:
$_SESSION['item']
重要
The get()
method WILL return flashdata items when
retrieving a single item by key. It will not return flashdata when
grabbing all userdata from the session, however.
しかしながら、もし(他のデータは読み込まずに)"フラッシュデータ" だけを読み込みたいなら、 getFlashdata()
メソッドを使います:
$session->getFlashdata('item');
また、配列としてフラッシュデータをすべて取得したいなら、単にキー引数を省略してください:
$session->getFlashdata();
注釈
getFlashdata()
メソッドは、アイテムが見つからない場合は NULL を返します。
もし次のリクエストでもフラッシュデータが必要であるなら、 keepFlashdata()
メソッドで保持することができます。
単一のフラッシュデータ、またはフラッシュデータの配列を渡せます。
$session->keepFlashdata('item');
$session->keepFlashdata(['item1', 'item2', 'item3']);
テンプデータ¶
CodeIgniter は "テンプデータ" をサポートします。特定の有効期限を持つセッションデータです。値の有効期限が切れた、またはセッションの有効期限が切れるか削除された後、 値は自動的に削除されます。
フラッシュデータと同様に、テンプデータ変数も CodeIgniter のセッションハンドラで内部的に管理されます。
すでにあるアイテムを "テンプデータ" としてマークするには、シンプルにそのキーと有効期限を(単位は秒で!) mark_as_temp()
メソッドに渡してください:
// 'item' は 300 秒後に消されます
$session->markAsTempdata('item', 300);
複数のアイテムをテンプデータとしてマークできますが、方法は2つあり、有効期限が同じかどうかによります:
// Both 'item' and 'item2' will expire after 300 seconds
$session->markAsTempdata(['item', 'item2'], 300);
// 'item' will be erased after 300 seconds, while 'item2'
// will do so after only 240 seconds
$session->markAsTempdata([
'item' => 300,
'item2' => 240
]);
テンプデータを追加するにはこうします:
$_SESSION['item'] = 'value';
$session->markAsTempdata('item', 300); // 5 分で期限切れ
または別の方法として、 setTempdata()
メソッドを使います:
$session->setTempdata('item', 'value', 300);
set_tempdata()
には配列を渡すこともできます:
$tempdata = ['newuser' => TRUE, 'message' => 'Thanks for joining!'];
$session->setTempdata($tempdata, NULL, $expire);
注釈
有効期限を省略するか 0 に設定した場合、デフォルトの有効期限 300 秒(5分)が使用されます。
テンプデータ変数を読み取るには、これもですがですが、 $_SESSION
スーパーグローバル配列でアクセスすることができます:
$_SESSION['item']
重要
The get()
method WILL return tempdata items when
retrieving a single item by key. It will not return tempdata when
grabbing all userdata from the session, however.
しかしながら、もし(他のデータは読み込まずに)"テンプデータ" だけを読み込みたいなら、 getTempdata()
メソッドを使います:
$session->getTempdata('item');
そしてもちろん、すべてのテンプデータを取得したい場合は:
$session->getTempdata();
注釈
The getTempdata()
method returns NULL if the item cannot be
found.
有効期限が切れる前にテンプデータ値を削除する必要がある場合は $_SESSION
配列を直接 unset してください:
unset($_SESSION['item']);
However, this won't remove the marker that makes this specific item to be
tempdata (it will be invalidated on the next HTTP request), so if you
intend to reuse that same key in the same request, you'd want to use
removeTempdata()
:
$session->removeTempdata('item');
セッションの破棄¶
現在のセッションをクリアするには (例えばログアウト時) 、単に PHP の session_destroy() 関数を使うか、 sess_destroy()
メソッドを使います。どちらもまったく同じです:
session_destroy();
// または
$session->destroy();
注釈
これはリクエスト内で行うセッション関連の最後の操作でなければなりません。すべてのセッションデータ(フラッシュデータとテンプデータを含む)は永続的に破棄され、その後は同じリクエスト内ではセッション機能は使えなくなります。
または stop()
メソッドでも完全にセッションを停止させることができます。古い session_id は削除され、すべてのデータは破棄され、セッション ID を保持するクッキーも破棄されます。
$session->stop();
セッションメタデータへのアクセス¶
CodeIgniter の以前のバージョン[訳注: 2.x系以前]では、セッションデータ配列はデフォルトで4つの項目を含んでいました: 'session_id'、'ip_address'、'user_agent'、'last_activity'です。
これはセッションを動かすために必要だった変数ですが、今の新しい実装には不要になりました。しかしながら、あなたのアプリケーションがこれらの値に依存しているということもあるでしょう。 そこで、これらにアクセスするための代替手段を記します:
- session_id:
session_id()
- ip_address:
$_SERVER['REMOTE_ADDR']
- user_agent:
$_SERVER['HTTP_USER_AGENT']
(unused by sessions)- last_activity: ストレージによります。ストレートな方法はありません。ごめんなさい!
Session Preferences¶
CodeIgniter は通常、セットアップしてすぐ動きます。しかしながら、セッションはいろいろなアプリケーションで非常に敏感な部品であるため、いくらか慎重に設定を行われなければなりません。オプションとその影響のすべてを考慮するため、どうか時間を取って検討してください。
You'll find the following Session related preferences in your app/Config/App.php file:
Preference | Default | Options | Description |
---|---|---|---|
sessionDriver | CodeIgniterSessionHandlersFileHandler | CodeIgniterSessionHandlersFileHandler CodeIgniterSessionHandlersDatabaseHandler CodeIgniterSessionHandlersMemcachedHandler CodeIgniterSessionHandlersRedisHandler | The session storage driver to use. |
sessionCookieName | ci_session | [A-Za-z_-] characters only | The name used for the session cookie. |
sessionExpiration | 7200 (2 hours) | Time in seconds (integer) | The number of seconds you would like the session to last. If you would like a non-expiring session (until browser is closed) set the value to zero: 0 |
sessionSavePath | NULL | None | Specifies the storage location, depends on the driver being used. |
sessionMatchIP | FALSE | TRUE/FALSE (boolean) | Whether to validate the user's IP address when reading the session cookie. Note that some ISPs dynamically changes the IP, so if you want a non-expiring session you will likely set this to FALSE. |
sessionTimeToUpdate | 300 | Time in seconds (integer) | This option controls how often the session class will regenerate itself and create a new session ID. 0 に設定すると、セッション ID の再生成を無効にします。 |
sessionRegenerateDestroy | FALSE | TRUE/FALSE (boolean) | Whether to destroy session data associated with the old session ID when auto-regenerating the session ID. FALSE に設定すると、データはガベージコレクタによってあとで削除されます。 |
注釈
上記のいずれも設定されていない場合、セッションライブラリは最後の手段として PHP の INI 設定を取得しようとします。古い CodeIgniter の 'sess_expire_on_close' と同様の動きです。 しかしながら、その振る舞いに依存してはなりません。予期しない結果を引き起こすか、将来変更される可能性があります。どうかすべてきちんと設定してください。
In addition to the values above, the cookie and native drivers apply the following configuration values shared by the IncomingRequest and Security classes:
Preference | Default | Description |
---|---|---|
cookieDomain | '' | セッションが適用されるドメイン |
cookiePath | / | セッションが適用されるパス |
cookieSecure | FALSE | 暗号化接続(HTTPS)でのみセッションクッキーを作成するかどうか |
注釈
'cookieHTTPOnly' の設定はセッションには影響しません。 HttpOnly パラメータはセキュリティ上の理由から常に有効になっています。Additionally, the 'cookiePrefix' setting is completely ignored.
Session Drivers¶
既に述べたように、セッションライブラリには 4 つのドライバ、つまりストレージエンジンがあります:
- CodeIgniterSessionHandlersFileHandler
- CodeIgniterSessionHandlersDatabaseHandler
- CodeIgniterSessionHandlersMemcachedHandler
- CodeIgniterSessionHandlersRedisHandler
By default, the FileHandler
Driver will be used when a session is initialized,
because it is the safest choice and is expected to work everywhere
(virtually every environment has a file system).
However, any other driver may be selected via the public $sessionDriver
line in your app/Config/App.php file, if you chose to do so.
しかし、それぞれのドライバには異なる注意点があり、使う前にそれら(後述します)に熟知しておくべきということを頭にとどめておいてください。
FileHandler Driver (the default)¶
The 'FileHandler' driver uses your file system for storing session data.
それは正確に PHP そのもののデフォルトセッション実装のように動作するといって差し支えありません。しかし場合により重要なこととなりますが、実際には同じコードではありません。それはいくつかの制限(と利点)を持っているということを忘れないでください。
具体的には、 PHP の session.save_path で使用されるディレクトリレベルとモードの形式 をサポートしていません。そのオプションのほとんどは、安全のためにハードコーディングされています。Instead, only
absolute paths are supported for public $sessionSavePath
.
知っておくべきもう一つの重要なこととして、広範囲に読み込み可能なディレクトリ、または共有ディレクトリをセッションファイルを格納するティレクトリとして使用していないことを確認してください。sessionSavePath ディレクトリに指定したものが ただ一人あなただけが アクセス可能であること確認してください。さもなくば、それを行うことができる誰もが、現在のセッションをどれでも盗むことができます("session fixation"「セッション固定攻撃」として知られています)。
UNIX ライクなオペレーティングシステムでは、通常 chmod コマンドによって 0700 モードで設定して保存されます。このモードはディレクトリの所有者だけが読み書き操作を可能にするものです。 But be careful because the system user running the script is usually not your own, but something like 'www-data' instead, so only setting those permissions will probably break your application.
かわりに、ご使用の環境に応じて、次のようにする必要があります:
mkdir /<アプリケーションディレクトリへのパス>/Writable/sessions/
chmod 0700 /<アプリケーションディレクトリへのパス>/Writable/sessions/
chown www-data /<アプリケーションディレクトリへのパス>/Writable/sessions/
Bonus Tip¶
あなたがたの何人かは、ファイルストレージは通常遅いので、おそらく別のセッションのドライバを選択するでしょう。これは半分だけ真実です。
非常に簡単なテストはおそらく、SQL データベースのほうが高速であると信じてしまうようにあなたをひっかけますが、しかし 99% のケースで、わずか数セッションだけ持っているあいだだけの真実です。セッションが積み重ねられサーバ負荷が増えるにしたがい――それが問題になったとき――ほぼ一貫してファイルシステムのほうがリレーショナルデータベースで組み上げるよりパフォーマンスに優れるでしょう。
つけくわえると、パフォーマンスだけが目的であるなら、 tmpfs (警告: 外部リソースです)の使い方を調べるといいかもしれません。それは燃え上がるがごとくセッションを速くします。
DatabaseHandler Driver¶
The 'DatabaseHandler' driver uses a relational database such as MySQL or PostgreSQL to store sessions. これは多くのユーザーに人気のある選択肢です。開発者にとって容易にアプリケーションからアクセス可能になるからです――単にデータベースにテーブルを新しく作るだけです。
しかしながら、満たされなければならないいくつかの条件があります:
- 持続的接続を使用することは で き ま せ ん 。
- cacheOn 設定が有効な接続では使用することは で き ま せ ん 。
In order to use the 'DatabaseHandler' session driver, you must also create this
table that we already mentioned and then set it as your
$sessionSavePath
value.
たとえばテーブル名として 'ci_sessions' を使用する場合、こうします:
public $sessionDriver = 'CodeIgniter\Session\Handlers\DatabaseHandler';
public $sessionSavePath = 'ci_sessions';
そしてもちろん、データベースにテーブルを作成します……
MySQL の場合:
CREATE TABLE IF NOT EXISTS `ci_sessions` (
`id` varchar(128) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`timestamp` int(10) unsigned DEFAULT 0 NOT NULL,
`data` blob NOT NULL,
KEY `ci_sessions_timestamp` (`timestamp`)
);
PostgreSQL の場合:
CREATE TABLE "ci_sessions" (
"id" varchar(128) NOT NULL,
"ip_address" varchar(45) NOT NULL,
"timestamp" bigint DEFAULT 0 NOT NULL,
"data" text DEFAULT '' NOT NULL
);
CREATE INDEX "ci_sessions_timestamp" ON "ci_sessions" ("timestamp");
また、 'sessionMatchIP' の設定に応じて PRIMARY KEY を追加する必要があります。次の例は MySQL と PostgreSQL の両方で動きます:
// sessionMatchIP = TRUE のとき
ALTER TABLE ci_sessions ADD PRIMARY KEY (id, ip_address);
// sessionMatchIP = FALSE のとき
ALTER TABLE ci_sessions ADD PRIMARY KEY (id);
// 以前のプライマリキーを削除するとき(設定を変更するときに使います)
ALTER TABLE ci_sessions DROP PRIMARY KEY;
You can choose the Database group to use by adding a new line to the applicationConfigApp.php file with the name of the group to use:
public $sessionDBGroup = 'groupName';
If you'd rather not do all of this by hand, you can use the session:migration
command
from the cli to generate a migration file for you:
> php spark session:migration
> php spark migrate
This command will take the sessionSavePath and sessionMatchIP settings into account when it generates the code.
重要
MySQL と PostgreSQL のデータベースのみが公式サポート対象です。ほかのデータベースではアドバイザリロック機構が提供されていないためです。ロックなしにセッションを使うと、特に AJAX を多用する場合において、あらゆる種類の問題を引き起こします。私たちはそのようなものはサポートしません。パフォーマンス問題を抱えている場合は、セッションデータを処理したあとに session_write_close()
を使用してください。
RedisHandler Driver¶
注釈
Redis はロック機構を提供していないので、このドライバのロックは最大 300 秒間保持される別の値によってエミュレートされています。
Redis はそのハイパフォーマンスさからキャッシュにとてもよく使われるストレージエンジンで、あなたが 'RedisHandler' セッションドライバを使用するのもまた、その性能の高さからでしょう。
欠点としては、リレーショナルデータベースほどには広く使えるわけではなく、 phpredis PHP 拡張モジュールをインストールしなければなりません。しかしそれは PHP にはバンドルされていません。 Chances are, you're only be using the RedisHandler driver only if you're already both familiar with Redis and using it for other purposes.
Just as with the 'FileHandler' and 'DatabaseHandler' drivers, you must also configure
the storage location for your sessions via the
$sessionSavePath
setting.
そのフォーマットはすこしだけそれらと異なり、また複雑です。最良の説明が phpredis 拡張の README ファイルでなされているので、私たちはそれへのリンクを渡すにとどめましょう:
警告
CodeIgniter のセッションライブラリは実際の 'redis' の session.save_handler
を使用して い ま せ ん 。上記リンクのパス形式に だけ 参考にしてください。
しかしながら、最も一般的なケースではシンプルな host:port
のペアで十分でしょう:
public $sessionDiver = 'CodeIgniter\Session\Handlers\RedisHandler';
public $sessionSavePath = 'tcp://localhost:6379';
MemcachedHandler Driver¶
注釈
Since Memcached doesn't have a locking mechanism exposed, locks for this driver are emulated by a separate value that is kept for up to 300 seconds.
The 'MemcachedHandler' driver is very similar to the 'RedisHandler' one in all of its properties, except perhaps for availability, because PHP's Memcached extension is distributed via PECL and some Linux distributions make it available as an easy to install package.
それ以外には、とくに偏見もひいきもなく、 Memcached は Redis と変わるところはないと言えましょう――これもまたキャッシュによく使われ、その速度で名高い製品です。
しかしながら重要な注意点として、Memcached により保証されることは唯一、Y 秒の期限を定められた値 X が Y 秒経過後に削除されていることだけです(必ずしもその時間より前には削除されないということではありません)。極めてまれではありますが、それによりセッションが失われる可能性があることを考慮するべきです。
The $sessionSavePath
format is fairly straightforward here,
being just a host:port
pair:
public $sessionDriver = 'CodeIgniter\Session\Handlers\MemcachedHandler';
public $sessionSavePath = 'localhost:11211';
Bonus Tip¶
複数サーバを使ったコロン区切りの値( :weight
)の 重みづけ パラメータもサポートされています。しかし、私たちはそれを信頼できるほどのテストはしていないことにご注意ください。
あなたが(あなた自身のリスクで)この機能を試してみたい場合、単にカンマ区切りで複数のサーバパスを並べます:
// 192.0.2.1 の重みづけ 1 と比べ、
// localhost はより高い優先度(5)を与えられます。
public $sessionSavePath = 'localhost:11211:5,192.0.2.1:11211:1';