Error handling PHP session in Mongodb

Asked

Viewed 71 times

0

I am using an Handler for php session in which you save the session data in Mongodb. However, while reloading the page at short intervals, it throws an error: "Failed to write Session data (user)" and recommends checking the "Session.save_path" setting. This error also occurs after using "header('Location: page-any.php')". Although this error does not prejudge current data in the global "$_SESSION" prevent new data from being entered in the database (or updated). As I use sessions to save tokens used in the validation of forms and some requests this disturbs... I searched references to this error, unsuccessful since the php manual only refers to this error in handling record sessions on disk on the server which is not my case as I am saving for Mongodb.

In "php.ini" "Session.save_habdler" and "Session.save_path" omitted (commented).

Mongodb version: 3.0.12

PHP version: 7.0.8

Version of mongodb extension: 1.1.8

Thanks in advance for references, content for reading or exclamations.

Mongocrud.php

// define default content and charset (text/html and UTF-8)
header("Content-type: text/html; charset=UTF-8");

/**
 * More info in:
 *    http://docs.php.net/set.mongodb
 *    http://mongodb.github.io/mongo-php-driver
 */

class MongoCRUD
{
  // defaults
  private $url = '127.0.0.1';
  private $port = '27017';
  private $base = 'local';
  private $errors;

  /**
   * Private function for display errors (matchs in tray|catch blocks)
   *
   * Private variable "errors" define if this function retur errors (defaut - development)
   */
  private function __ERRORSTRYCATCH__($e)
  {
       // check status code
       if($this->errors == true){
          $filename = basename(__FILE__);
          echo "<br><br>Exception: " . $e->getMessage() . "<br>";
          echo "In File: " . $e->getFile() . "<br>";
          echo "In Line: " . $e->getLine() . "<br>";
       }
  }

  private function wc()
  {
       // Construct a write concern
       return new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY,100);
  }

  private function rp()
  {
       // Construct a read preference
       return new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY_PREFERRED,[]);
  }

  private function open()
  {
       return new MongoDB\Driver\Manager("mongodb://" . $this->url . ":" . $this->port . "/" . $this->base);
  }


  private function bulk()
  {
       return new MongoDB\Driver\BulkWrite;
  }

  private function query($filter = false)
  {
       if($filter){
          return new MongoDB\Driver\Query($filter);
       }else{
          return new MongoDB\Driver\Query([]);
       }

  }

  /**
   * $database {string} set database for operation
   * $options  {array}  set options. 
   */
   function __construct($database = false, $options = false)
   {
        // set default variables
        $this->errors = $options['err'] ?? true;
        // check if have database
        if(!$database){
           return false;
        }else{
           // define data base
           $this->base = $database;
        }
   }

   public function create($collection, $document)
   {
        // open manager
        $manager = self::open();
        // open bulk
        $bulk = self::bulk(['ordered' => true]);
        // bulk insert
        $bulk->insert($document);
        //
        try{
           // grab result
           $result = $manager->executeBulkWrite($this->base . '.' . $collection, $bulk, self::wc()); 
           // check
           if($result->getInsertedCount() === 1){
              return true;
           }else{
              return false;
           }

        }catch(MongoDB\Driver\Exception\Exception $e){
           // shutdown error
           self::__ERRORSTRYCATCH__($e);
           return false;
        }
   }

   public function reader($collection, $document = false, $filter = false)
   {
        // define document
        $document = $document ? $document : [];
        // define query
        $query = self::query($filter) ?? self::query();
        // open manager
        $manager = self::open();
        //
        try{
           // cursor
           $cursor = $manager->executeQuery($this->base . '.' . $collection, $query, self::rp());
           // store
           $multiples = [];
           // loop
           foreach($cursor as $document){
              array_push($multiples, $document);
           }

           // check if have result
           if(count($multiples) == 0){
              return false;
           }else{
              return $multiples;
           }

        }catch(MongoDB\Driver\Exception\Exception $e){
           // shutdown error
           self::__ERRORSTRYCATCH__($e);
           return false;
        }
   }

   public function update($collection, $filter, $newObj, $options = false)
   {
        // define options
        if($options != false && is_array($options)){
           $options = array_merge(["multi" => false, "upsert" => false], $options);
        }else{
           $options = ["multi" => false, "upsert" => false];
        }
        // open manager
        $manager = self::open();
        // open bulk
        $bulk = self::bulk();    
        // bulk update
        $bulk->update($filter, $newObj, $options);
        //
        try{    
           // grab result
           $result = $manager->executeBulkWrite($this->base . '.' . $collection, $bulk, self::wc());
           // check
           if($result->getModifiedCount() >= 1){
              return true;
           }else{
              return false;
           }

        }catch(Exception $e){
           // shutdown error
           self::__ERRORSTRYCATCH__($e);
           return false;
        }
   }

   public function delete($collection, $filter, $limit = false)
   {
        /**
         *  WARNING! $limit zero "0" delete all matches in collection! RISK ATENTION HERE!
         *  Default param is 0...
         */
        $limit   = (is_bool($limit) && $limit == true) ? ["limit" => 1] : ["limit" => 0];
        // open manager
        $manager = self::open();
        // open bulk
        $bulk    = self::bulk();
        // bulk delete
        $bulk->delete($filter, $limit);
        //
        try{
           // grab result
           $result = $manager->executeBulkWrite($this->base . '.' . $collection, $bulk, self::wc());
           // check
           if($result->getDeletedCount() >= 1){
              return true;
           }else{
              return false;
           }

        }catch(MongoDB\Driver\Exception\Exception $e){
           // shutdown error
           self::__ERRORSTRYCATCH__($e);
           return false;
        }
     }


}

Mongohandlersession.php

class HandlerSessionManager
{
  private $dbCollection;
  private $dbSession;
  private $expire;
  private $token;
  private $clean;

  public function __construct($options = false) {
      // define name of colection (set session_name() or default session_name())
      $this->dbCollection = $options['collection'] ?? session_name();

      // define database for connection in MongoDB (if no have.. create.)
      $this->dbSession    = new MongoCRUD( ( $options[ 'databasename' ] ?? 'SessionManager' ) );

      // define expiration time session (get default or choose (options or default 1 hour))
      $this->expire       = get_cfg_var( "session.gc_maxlifetime" ) ?? ( $options['expire'] ?? 3600 );

      // define token (for request session values in another fonts e.g: in nodejs)
      $this->token        = $options[ 'token' ] ?? false;

      // define if use auto_garbage function for clean old sessions (default false)
      $this->clean        = $options[ 'force_garbage' ] ? true : false;

      // define name of session
      session_name($this->dbCollection);

      // set save handler
      session_set_save_handler(
           [ $this, 'open'    ],
           [ $this, 'close'   ],
           [ $this, 'read'    ],
           [ $this, 'write'   ],
           [ $this, 'destroy' ],
           [ $this, 'gc'      ]
      );



      // check if session already started
      if(!isset($_SESSION)){
         session_start();
      }

      // shutdown
      @register_shutdown_function('session_write_close');

      // auto call
      self::auto_garbage();
  }

  public function open()
  {
      if($this->dbSession){
         return true;
      }else{
         return false;
      }
  }

  public function close()
  {
      $this->dbSession = null;
      return true;
  }

  public function read($id)
  {
      $doc = $this->dbSession->reader( $this->dbCollection, ["_id" => $id] );

      if(is_array($doc)){
         return $doc[0]->sessionData;
      }else{
         return "";
      }
  }

  public function write($id, $data)
  {
      $create = $this->dbSession->update( $this->dbCollection, ["_id" => $id], ['$set' => ["_id" => $id, "token" => $this->token, "sessionData" => $data, "expire" => ( time() + $this->expire )] ], ["upsert" => true] );

      return $create;
  }

  public function destroy($id)
  {
      $result = $this->dbSession->delete( $this->dbCollection, ["_id" => $id] );

      return $result;
  }

  public function gc()
  {
      $result = $this->dbSession->delete( $this->dbCollection, false, ["expire" => ['$lt' => time()]] );

      return $result;
  }

  public function auto_garbage()
  {
      if($this->clean){
         $this->dbSession->delete( $this->dbCollection, ["expire" => ['$lt' => time()]] );
      }
  }

  public function __destruct()
  {
      @session_write_close();
  }
}

index php.

require 'mongodb_/MongoCRUD.php';

require 'mongodb_/MongoHandlerSession.php';

$options = [
   'databasename'  => 'SessionManager',
   'collection'    => 'PHPSESSID',
   'expire'        =>  1440,  // it's don't is majority set. It is optional case php.ini no have value set
   'token'         =>  false, // 'YOUR_SUPER_ENCRYPTED_TOKEN'
   'force_garbage' =>  true
];
// init class
new HandlerSessionManager($options);

// Usage
$_SESSION['foo'] = 'bar';
  • You can post the save Handler you are using ?

  • posted Handler and crud

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.