🗒️

CakePHPの新旧バージョンでSessionを共有する

に公開

概要

CakePHP2系のバージョンアップを進めています。
段階的な移行をするために、2系と3系以上のバージョンを同時に動かせる必要があります。
セッションに色々な情報が入っているため共有する必要があるのですが、そのままでは共有できなかったので、調査した内容などを書き残しておきます。

結論

https://github.com/cakephp/cakephp/pull/11456
で紹介されているように、CakePHP2系側で設定変更をすることで、セッションを共有できます。
該当のPRは2.10.6で入っているようなので、それより前のバージョンを利用している場合には既存のシステムのバージョンアップが必要になります。

詳細

CakePHPの変更点について

CakePHP2から3は大幅に書き換えられています。
Sessionについても同様なのですが、移行ガイドを見ると廃止になった関数などが書いてあるのみで、具体的な変更部分や何が変わっているのかについてはあまり明確にはわかりません。
これはSessionのみの現象ではなく全体的にドキュメントだけ見ていればOKというわけではないという落とし穴があります。

以下、 https://book.cakephp.org/2/ja/development/sessions.html より引用

セッション
セッションクラスは static ではなくなり、代わりにセッションが request オブジェクトを介して アクセスすることができます。セッションオブジェクトを使用するためには、 セッション ドキュメントをご覧ください。
Cake\Network\Session と関連するセッションクラスは Cake\Network 名前空間の下に移動されました。
SessionHandlerInterface は、PHP 自体が提供するようになりましたので削除されました。
Session::$requestCountdown プロパティーは削除されました。
セッションの checkAgent 機能が削除されました。その機能は、 chrome のフレームや flash player が関与するとき、多くのバグを引き起こしました。
セッション用データベーステーブル名は cake_sessions の代わりに sessions になります。
セッションクッキーのタイムアウトは、自動的にセッションデータのタイムアウトと並行して更新されます。
セッションクッキーのパスは、"/" の代わりにアプリのベースパスがデフォルトになります。 新しい設定変数 Session.cookiePath は、クッキーのパスをカスタマイズするために 追加されました。
新しい便利なメソッド Cake\Network\Session::consume() は、 セッションデータの読み取りと削除を1度に行うするために追加されました。
Cake\Network\Session::clear() の引数 $renew のデフォルト値は、 true から false に変更されました。

何が違うのか

Issueでも指摘されている通り、Sessionで保有しているTimeの扱いが異なっています
CakePHP2系ではTimeが有効期限が切れる時間を示しています。
CakePHP3系移行では、Timeは現在時刻を表しています。
https://github.com/cakephp/cakephp/issues/10563

CakePHP2系の該当部分
https://github.com/cakephp/cakephp/blob/2.10.5/lib/Cake/Model/Datasource/CakeSession.php#L360-L368

Cake3系の該当部分
https://github.com/cakephp/cakephp/blob/3.10.5/src/Http/Session.php#L638-L652

CakePHP2で作成したSessionをCakePHP3でアクセスすると現在時刻より先の時刻にはなるのですが、セッションの有効期限は切れてないので、Sessionの値はリセットされません。
一方、CakePHP3系で作成したSessionは現在時刻となるため、CakePHP2でアクセスすると常に有効期限切れとして判断されてしまいます。

修正方法

結論でも書きましたが、CakePHP2側のオプションとして値が設定されています。
https://github.com/cakephp/cakephp/pull/11456

具体的には、以下のような記述を app.php などに追加してあげればOKです。

Configure::write('Session.useForwardsCompatibleTimeout', true);

最後に

バージョンアップに従って認証方法が変わったり、Sessionの内部的な保持方法が変わることが結構多いので、いい感じにうまく動かすのは大変ですね。

ちなみにFlaskでも同様のことがあり、謎のEPOCH_TIMEが使われているようなこともありました。
https://zenn.dev/link/comments/064ed5dd1c5137

DELTAテックブログ

Discussion