sql >> データベース >  >> RDS >> Mysql

PHPセッションデータをファイルシステムではなくデータベースに保存するにはどうすればよいですか?

    数時間のデバッグの過程で、多数のGoogle検索で参照された記事と、こちらこちら およびこちら すべてが無効または古い情報を提供します。

    セッションデータをデータベースに保存する際に[重大な]問題を引き起こす可能性のあるもの:

    • オンラインのすべての例では、 session_set_save_handlerを「埋める」ことができると述べています。 、 register_shutdown_function('session_write_close')も設定する必要があるとは記載されていません。 あまりにも(参照 )。

    • いくつかの(古い)ガイドは古いSQLデータベース構造を参照しているため、すべきではありません。 利用される。セッションデータをデータベースに保存するために必要なデータベース構造は次のとおりです。id /アクセス /データ 。それでおしまい。いくつかの「ガイド」と例で見たように、さまざまな追加のタイムスタンプ列は必要ありません。

      • 古いガイドのいくつかには、 DELETE * FROM ...などの古いMySQL構文もあります。
    • [私の質問で作成された]クラスは、 実装 する必要があります。 SessionHandlerInterface sessionHandler の実装を提供するガイド(上記参照)を見てきました これは適切なインターフェースではありません。おそらく、以前のバージョンのPHPには、わずかに異なる方法がありました(おそらく<5.4)。

    • セッションクラスのメソッドは必須 PHPマニュアルで設定されている値を返します。繰り返しになりますが、おそらく5.4より前のPHPから継承されていますが、私が読んだ2つのガイドでは、 class-> open 読み取る行を返しますが、PHPマニュアルの状態 trueを返す必要があること またはfalse のみ。

    • これが私の最初の問題の原因です :カスタムセッション名を使用していました(実際には、セッション名としてのIDとセッションIDのは同じものです!この非常に優れたStackOverflow投稿 による これにより、128文字のセッション名が生成されていました。セッション名は、セッションを危険にさらし、セッションハイジャック その場合、名前/IDを長くすることは非常に良いことです。

      • ただし、 MySQLがセッションIDをサイレントにスライスしていたため、これにより問題が発生しました。 128文字ではなく32文字に減少したため、データベースでセッションデータを見つけることができませんでした。これは完全にサイレントな問題でした(おそらく私のデータベース接続クラスがそのようなことの警告をスローしなかったためです)。しかし、これは注意すべきものです。データベースからのセッションの取得で問題が発生した場合は、最初にフルであることを確認してください。 セッションIDは、指定されたフィールドに保存できます。

    ですから、これらすべてが邪魔にならないように、追加する追加の詳細もいくつかあります:

    PHPのマニュアルページ(上記のリンク)には、クラスオブジェクトに不適切な行の山が示されています:

    これをクラスコンストラクターに入れても同様に機能します:

    class MySessionHandler implements SessionHandlerInterface {
    
        private $database = null;
    
    public function __construct(){
    
        $this->database = new Database(whatever);
    
        // Set handler to overide SESSION
        session_set_save_handler(
            array($this, "open"),
            array($this, "close"),
            array($this, "read"),
            array($this, "write"),
            array($this, "destroy"),
            array($this, "gc")
            );
        register_shutdown_function('session_write_close');
        session_start();
        }
    ...
    }
    

    これ つまり、出力ページでセッションを開始するために必要なのは次のとおりです。

    <?php
    require "path/to/sessionhandler.class.php"; 
    new MySessionHandler();
    
    //Bang session has been setup and started and works
    

    参考までに、完全なセッション通信クラスは次のとおりです。これはPHP 5.6で動作します(おそらく7ですが、7ではまだテストされていません)

    <?php
    /***
     * Created by PhpStorm.
     ***/
    class MySessionHandler implements SessionHandlerInterface {
        private $database = null;
    
        public function __construct($sessionDBconnectionUrl){
            /***
             * Just setting up my own database connection. Use yours as you need.
             ***/ 
    
                require_once "class.database.include.php";
                $this->database = new DatabaseObject($sessionDBconnectionUrl);
    
            // Set handler to overide SESSION
            session_set_save_handler(
                array($this, "open"),
                array($this, "close"),
                array($this, "read"),
                array($this, "write"),
                array($this, "destroy"),
                array($this, "gc")
            );
            register_shutdown_function('session_write_close');
            session_start();
        }
    
        /**
         * Open
         */
        public function open($savepath, $id){
            // If successful
            $this->database->getSelect("SELECT `data` FROM sessions WHERE id = ? LIMIT 1",$id,TRUE);
            if($this->database->selectRowsFoundCounter() == 1){
                // Return True
                return true;
            }
            // Return False
            return false;
        }
        /**
         * Read
         */
        public function read($id)
        {
            // Set query
            $readRow = $this->database->getSelect('SELECT `data` FROM sessions WHERE id = ? LIMIT 1', $id,TRUE);
            if ($this->database->selectRowsFoundCounter() > 0) {
                return $readRow['data'];
            } else {
                return '';
            }
        }
    
        /**
         * Write
         */
        public function write($id, $data)
        {
            // Create time stamp
            $access = time();
    
            // Set query
            $dataReplace[0] = $id;
            $dataReplace[1] = $access;
            $dataReplace[2] = $data;
            if ($this->database->noReturnQuery('REPLACE INTO sessions(id,access,`data`) VALUES (?, ?, ?)', $dataReplace)) {
                return true;
            } else {
                return false;
            }
        }
    
        /**
         * Destroy
         */
        public function destroy($id)
        {
            // Set query
            if ($this->database->noReturnQuery('DELETE FROM sessions WHERE id = ? LIMIT 1', $id)) {
                return true;
            } else {
    
                return false;
            }
        }
        /**
         * Close
         */
        public function close(){
            // Close the database connection
            if($this->database->dbiLink->close){
                // Return True
                return true;
            }
            // Return False
            return false;
        }
    
        /**
         * Garbage Collection
         */
        public function gc($max)
        {
            // Calculate what is to be deemed old
            $old = time() - $max;
    
            if ($this->database->noReturnQuery('DELETE FROM sessions WHERE access < ?', $old)) {
                return true;
            } else {
                return false;
            }
        }
    
        public function __destruct()
        {
            $this->close();
        }
    
    }
    

    使用法:クラスコードテキストのすぐ上に示されているように。




    1. oraclesqlからpandasdfへのデータのロードを高速化する方法

    2. ドミノの秘密、またはドミノゲームデータモデル

    3. データベースユーザー管理:MariaDBのロールの管理

    4. MySQLでテーブルのピボットを解除する