2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CakePHP4 で Session 情報を DB で管理するようにする

Last updated at Posted at 2020-03-21

CakePHP4 プロジェクトを作った状態だと、Session 情報の格納は php.ini の標準設定に従うことになっているので、ファイルで管理することになっていると思います。

ロードバランサー配下で負荷分散してサービス提供することを考えると、Session 情報がサーバー単位で管理されることを避ける必要があります。

memcached 等のキャッシュサーバーを使う方法もありますが、大規模なサービスでなければそこまでする必要はないと思っています。
まずは DB で Session 情報を管理して、レスポンス等の問題が発生したらキャッシュサーバーへ変更するのが、程よい妥協点です。

僕の経験上ですが DB Session 情報管理でレスポンスの問題が発生するのはかなりレアです。
ステートレスを意識している現状だと、Session に格納する情報なんてログインユーザーや CSRF とかのセキュリティに関する情報程度ですしね。

この記事でわかること

参考

事前準備

docker-compose up -d
バージョン
docker Docker version 19.03.8, build afacb8b
docker-compose docker-compose version 1.25.4, build 8d51620a
CakePHP4 4.0.4

マイグレーションファイルの作成

CakeBook では、用意している SQL ファイルを実行して sessions テーブルを作成することになっていますが 、これだと開発者への作業手順が増えてしまうのでマイグレーションを使って sessions テーブルを作成します。

コンテナを経由して bake を実行し、マイグレーションファイルのテンプレートを作成します。

docker exec -it app bin/cake bake migration CreateSessions

change メソッドを ./config/schema/sessions.sql と同じ内容を記載します。

config/Migrations/yyyymmddhhmiss_CreateSessions.php
class CreateSessions extends AbstractMigration
{
    /**
     * Change Method.
     *
     * More information on this method is available here:
     * http://docs.phinx.org/en/latest/migrations.html#the-change-method
     * @return void
     */
    public function change()
    {
        $this->table('sessions', ['id' => false, 'primary_key' => ['id']])
            ->addColumn('id', 'char', [
                'default' => null,
                'limit' => 40,
                'null' => false,
            ])
            ->addColumn('data', 'blob', [
                'default' => null,
                'limit' => null,
                'null' => true,
            ])
            ->addColumn('expires', 'integer', [
                'default' => null,
                'limit' => 10,
                'null' => false,
                'signed' => false,
            ])
            ->addColumn('created', 'datetime', [
                'default' => 'CURRENT_TIMESTAMP',
                'limit' => null,
                'null' => true,
            ])
            ->addColumn('modified', 'datetime', [
                'default' => 'CURRENT_TIMESTAMP',
                'update' => 'CURRENT_TIMESTAMP',
                'limit' => null,
                'null' => true,
            ])
            ->create();
    }
}

マイグレーションの実行

Sessions テーブルのマイグレーションファイルを DB へ適用します。

docker exec -it app bin/cake migrations migrate

Session 管理方法を DB へ変更

./config/app.php の Session 設定の記述を変更します。

config/app.php
    'Session' => [
        'defaults' => 'database',
        'cookie' => env('APP_NAME'),
        'timeout' => 1440, // 1day(単位:分)
        'ini' => [
            'session.cookie_secure' => filter_var(env('SERVER', false), FILTER_VALIDATE_BOOLEAN),
            'session.cookie_path' => '/',
        ]
    ],

本当は、defaults のみの変更で良いのですが、他も変更しています。
この Session の設定って意外とややこしい印象があります。毎回、ググって最適な設定を探しているイメージです。
今回は最低限として、上記のような設定にしました。

cookie で cookie 名を指定しています。自分のアプリの Cookie だっということを明示したいです。

timeout は、アプリの要件次第ですが、これが一番クセモノだと思っています。これだけで本当に効いているのか毎回うなりながら確認している気がします。

session.cookie_secure は必須です。https 環境下では、必ず Secure フラグを ON にする必要があります。今どきであれば、Secure フラグが OFF なのはローカル環境ぐらいだと思います。ローカル環境も https 経由にすれば、常に ON で良いと思います。

session.cookie_path はデフォルトが "/" なので指定不要な気もしますが、明示したくて記載しています。アプリをパスで切り分けて提供する環境ではとても重要な設定です。

動作確認

Session を使うと sessions テーブルへレコードが追加れます。
暫定で、PagesController へ Session への書き込みの記述を追加して確認します。

src/Controller/PagesController.php
    public function index(): ?Response
    {
        // 試しに Session へ書き込む
        $this->getRequest()->getSession()->write('key', 'value');

        return $this->render();
    }

これで http://localhost へアクセスすると sessions テーブルへレコードが追加されていることを確認できます。

補足) schema-dump-default.lock の管理について

schema-dump-default.lock はコンフリクトの原因になるので、コミット対象から外しています。
bin/cake bake migration_diff とかを使ったことがないので、コミット対象から外したことで困ったことはありません。

.gitignore
# ... いろいろな記述
# Migration
schema-dump-default.lock
# ... いろいろな記述

補足) マイグレーションファイル名について

極力 CakePHP のルールに従えば良いと思うのですが、まぁ、あくまで「極力」だと思います。
作っているといろいろあるので、従わないほうがわかりやすいときもあると思います。

パターン 説明
(/^(Create)(.*)/) テーブル作成 CreateTasks
(/^(Drop)(.*)/) テーブル削除 DropTasks
(/^(Add).(?:To)(.)/) カラム追加 AddDescriptionToTasks
(/^(Remove).(?:From)(.)/) カラム削除 RemoveDescriptionFromTasks
(/^(Alter)(.*)/) テーブル変更 AlterTasks
(/^(Alter).(?:On)(.)/) カラム変更 AlterDescriptionOnTasks

補足) change メソッドで使えるコマンド

change / up / down のどのメソッドを使えば良いか悩むときは多々あると思うので、参考をのせます。

createTable
renameTable
addColumn
renameColumn
addIndex
addForeignKey

僕自身があまり bin/cake migrations rollback を使わなくて、 bin/cake migrations rollback で正しく戻ることの検証もあんまりしないんですよね、、、
なので、 down メソッドが空っというのは結構見ます。

Migration のテストって書いている人いるんでしょうか!?
しっかりした開発だとそこもきっちり検証するんでしょう!!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?