title: CodeIgniter3セッションライブラリ和訳の「訳者注」
slug: codeigniter3-session-yakushachuu
date: 2016-04-09T15:45:00+09:00
#lastmod:
archives: [ “2016”, “2016/04” ]
tags: [ “CodeIgniter3”, “flashdata”, “PHP5”, “PHP7”, “tempdata”, “セッション” ]
categories: [ codeigniter3 ]

draft: false

さきほどCodeIgniter3セッションライブラリのマニュアル和訳を完了しました。全部で1000行以上、マニュアルの各ページの中でも一番長い部類のものでした。さきほどPull Requestを行ったので、数日のうちに公開されることでしょう。

http://pneskin2.nekoget.com/codeigniter/3/user_guide/libraries/sessions.html

しかし訳していて、翻訳の中には書くことのできない「訳者注」も多く感じており、ここに別記事として書いてみたいと思います。

セッションライブラリはCodeIgniter3でほぼ作り直された

マニュアルの中にも書いてありますが、CodeIgniter2のセッションライブラリはバグが多く、3ではほとんど作り直されています。ですので、セッションの不具合を嫌っていた人はいちど3のセッションライブラリを見直してみられると良いと思います。

中を覗いてみると、セッションの根幹部分はPHPの$_SESSIONをそのまま使っています。CodeIgnire2系では完全自前実装でしたが、稼働実績が非常に多いものに乗せ換えたわけです。当然、不具合の多くは解消されました。

しかしその考えを進めれば「ライブラリなんか使わずに素の$_SESSIONをそのまま使えばいいじゃない」という話にもなり、それで済むならまさにその通りなのですが、セッションの有効期限やらを気にしはじめると「素のセッションではなくライブラリで一通りの設定をデフォルトでやってあげたほうがいいんじゃないの」というのがセッションライブラリが提供されている理由かと思っています(根拠のない推測です)。
CodeIgniterのメリットはデフォルト設定でそれなりに動くことです。

flashdataとtempdata

CodeIgniterのセッション機能はflashdataとtempdataを提供しています。ともにリクエストをまたぐ一時的なデータの保存場所として、一見便利です。しかし使い方を誤ると不可解な動作になることが多く、ともするとバグ扱いを受けるので要注意です。

flashdataはリダイレクト用にしか使えない

flashdataは私が知る限りではsymfony1系ですでに登場してるので2006年ごろには広く知られているものですが、正しく使えているかというと、むしろチームのスキル次第では「コーディング規約で使用禁止にしたほうがいいのではないか」と思うぐらい使いどころが難しいです。

マニュアル中では「Ajaxを多用する際はパフォーマンスに注意」という趣旨のことが書かれていますが、Ajaxを使用するしないにかかわらず、flashdataは同時アクセスに注意です。
具体的には、imgタグのsrcがリンク切れを起こしていると404ページを返す際にmod_rewriteやngx_http_rewrite_moduleでindex.phpが呼び出され、セッション初期化が走ってしまい、flashdataは消えてしまいます。imgタグのリンク切れなのでhtmlを返した直後のアクセスです。

つまり、ページを表示したらその瞬間にflashdataは消えます。「次のリクエスト」には引き継がれますが「次の画面」には引き継がれないのです

よほど注意深くURLを設計してmod_rewriteを設定してやるか、リンク切れは絶対に出さないという体制を作り上げない限り、flashdataは本当に一瞬で消えてしまい、まるでバグのようにふるまいます。また、リンク切れがなくてもAjaxが走ればやはりセッションが初期化され、flashdataは消えてなくなります

flashdataのユースケースは「更新ボタンを押したら一覧画面に戻って”更新しました”のメッセージを出す」といった用途です。このユースケースでは

  更新ボタンを押す -> 更新処理をしてflashdata設定、redirect -> 一覧ページ表示

といったものです。

重要なのはredirectです。redirectをする限りではリンク切れもAjaxも発生することがなく、「次のリクエスト=次の画面」を保証できます。つまり、redirectを使うシーンではflashdataはうまく機能します。それ以外では、何かしら別のリクエストが挟まってしまい、うまく動かないでしょう。

tempdataは次善策か?

tempdataはASP.NETで使われているもののようですが、私にはユースケースが思いつきません。

flashdataが仕組み上機能しない場合、つまりAjaxが1画面に2個以上ある場合には都合良くふるまうでしょう。APIファーストで作っている場合はflashdataを引き継がせたい先が必ずしも「次のリクエスト」にならないため、flashdataは使えません。tempdataなら指定の秒数は生き残るので、どの順番でAjaxが呼び出されてもきちんと値は引き継がれます。

しかしそれは実際には設計ミスに近いと思います。tempdataは何秒で消えるのが妥当か、客観的な判断を下せるシーンが思いつきません。本来は秒数で縛るものではないのです。

しかしながらまあ、実際のところは「適当に8秒で」とかやっつけで決めてしまっても害悪はなさそうなので「ちょっと丈夫なflashdata」ぐらいの利用方法でもいいのかなと思います。flashdataを使って不可解な動作に悩まされるぐらいなら、コーディング規約でtempdata一本で縛ったほうがみんな幸せになれそうです。

つまり次善策としてtempdataはそれなりにうまく機能するでしょう。ただし、1リクエストのレスポンスに10秒かかるなど重いアプリの場合にはご注意ください。