CodeIgniter Session Problem

“Why my user session keep expiring?” “Why CodeIgniter session expires when the page refreshed?

Bagi yang sudah sering menggunakan CI biasanya pernah mengalami masalah session problem ini. Usut punya usut dan cari punya cari, ternyata banyak juga yang mengalami masalah serupa. Di forum CodeIgniter pun ada beberapa thread yang posting masalah ini. Kenapa sessionnya expired terus? Atau malah tidak bekerja dengan semestinya di Internet Explorer versi lawas sedangkan di browser lain tidak masalah.

Banyak yang bilang session class si CI ini unreliable. Well, yes it is. I couldn’t agree more with it. CodeIgniter membuat session class-nya ini tidak menggunakan native session-nya PHP, tetapi CI generate sendiri session data mereka. Alasannya agar session lebih fleksibel bagi developer.

Untuk masalah diatas, ini salah satu workaround-nya. Menggunakan external library yang dibikin oleh mas Dariusz Debowczyk yang cerdas nan brilian. Skrip session class-nya dapat diunduh di tautan berikut (atau di akhir post ini) :

http://codeigniter.com/wiki/Dariusz_Debowczyk%27s_Session_Class

Cara menggunakannya cukup simpel, copy dan paste skrip lalu save di direktori “libraries” dengan nama Session.php. Kemudian tinggal panggil library seperti biasa, $this->load->library(“session”); atau didefinisikan di file config/autoload.php di option library-nya. Problem solved! 🙂

Menurut posting di thread forum CI, library ini berjalan pada CodeIgniter versi 1 dan 2. Saya sudah coba gunakan dan jalan baik-baik saja di versi 2. Di bawah ini skrip session class mas Darius saya kutip untuk mempermudah copy dan pastenya.

[code lang=”php”]

  makes dw cs4 happy

/**
* Session class using native PHP session features and hardened against session fixation.
*
* @package     CodeIgniter
* @subpackage  Libraries
* @category    Sessions
* @author      Dariusz Debowczyk, Matthew Toledo
* @link        http://www.philsbury.co.uk/index.php/blog/code-igniter-sessions/
*/
class CI_Session {

    var $flashdata_key     = 'flash'; // prefix for "flash" variables (eg. flash:new:message)

    function CI_Session()
    {
        $this->object =& get_instance();
        log_message('debug', "Native_session Class Initialized");
        $this->_sess_run();
    }

    /**
    * Regenerates session id
    */
    function regenerate_id()
    {
        // copy old session data, including its id
        $old_session_id = session_id();
        $old_session_data = $_SESSION;

        // regenerate session id and store it
        session_regenerate_id();
        $new_session_id = session_id();

        // switch to the old session and destroy its storage
        session_id($old_session_id);
        session_destroy();

        // switch back to the new session id and send the cookie
        session_id($new_session_id);
        session_start();

        // restore the old session data into the new session
        $_SESSION = $old_session_data;

        // update the session creation time
        $_SESSION['regenerated'] = time();

        // session_write_close() patch based on this thread
        // http://www.codeigniter.com/forums/viewthread/1624/
        // there is a question mark ?? as to side affects

        // end the current session and store session data.
        session_write_close();
    }

    /**
    * Destroys the session and erases session storage
    */
    function destroy()
    {
        unset($_SESSION);
        if ( isset( $_COOKIE[session_name()] ) )
        {
            setcookie(session_name(), '', time()-42000, '/');
        }
        session_destroy();
    }

    /**
    * Alias for destroy(), makes 1.7.2 happy.
    */
    function sess_destroy()
    {
        $this->destroy();
    }

    /**
    * Reads given session attribute value
    */
    function userdata($item)
    {
        if($item == 'session_id'){ //added for backward-compatibility
            return session_id();
        }else{
            return ( ! isset($_SESSION[$item])) ? false : $_SESSION[$item];
        }
    }

    /**
    * Sets session attributes to the given values
    */
    function set_userdata($newdata = array(), $newval = '')
    {
        if (is_string($newdata))
        {
            $newdata = array($newdata => $newval);
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                $_SESSION[$key] = $val;
            }
        }
    }

    /**
    * Erases given session attributes
    */
    function unset_userdata($newdata = array())
    {
        if (is_string($newdata))
        {
            $newdata = array($newdata => '');
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                unset($_SESSION[$key]);
            }
        }
    }

    /**
    * Starts up the session system for current request
    */
    function _sess_run()
    {
        session_start();

        $session_id_ttl = $this->object->config->item('sess_expiration');

        if (is_numeric($session_id_ttl))
        {
            if ($session_id_ttl > 0)
            {
                $this->session_id_ttl = $this->object->config->item('sess_expiration');
            }
            else
            {
                $this->session_id_ttl = (60*60*24*365*2);
            }
        }

        // check if session id needs regeneration
        if ( $this->_session_id_expired() )
        {
            // regenerate session id (session data stays the
            // same, but old session storage is destroyed)
            $this->regenerate_id();
        }

        // delete old flashdata (from last request)
        $this->_flashdata_sweep();

        // mark all new flashdata as old (data will be deleted before next request)
        $this->_flashdata_mark();
    }

    /**
    * Checks if session has expired
    */
    function _session_id_expired()
    {
        if ( !isset( $_SESSION['regenerated'] ) )
        {
            $_SESSION['regenerated'] = time();
            return false;
        }

        $expiry_time = time() - $this->session_id_ttl;

        if ( $_SESSION['regenerated']  $newval);
        }

        if (count($newdata) > 0)
        {
            foreach ($newdata as $key => $val)
            {
                $flashdata_key = $this->flashdata_key.':new:'.$key;
                $this->set_userdata($flashdata_key, $val);
            }
        }
    }

    /**
    * Keeps existing "flash" data available to next request.
    */
    function keep_flashdata($key)
    {
        $old_flashdata_key = $this->flashdata_key.':old:'.$key;
        $value = $this->userdata($old_flashdata_key);

        $new_flashdata_key = $this->flashdata_key.':new:'.$key;
        $this->set_userdata($new_flashdata_key, $value);
    }

    /**
    * Returns "flash" data for the given key.
    */
    function flashdata($key)
    {
        $flashdata_key = $this->flashdata_key.':old:'.$key;
        return $this->userdata($flashdata_key);
    }

    /**
    * PRIVATE: Internal method - marks "flash" session attributes as 'old'
    */
    function _flashdata_mark()
    {
        foreach ($_SESSION as $name => $value)
        {
            $parts = explode(':new:', $name);
            if (is_array($parts) && count($parts) == 2)
            {
                $new_name = $this->flashdata_key.':old:'.$parts[1];
                $this->set_userdata($new_name, $value);
                $this->unset_userdata($name);
            }
        }
    }

    /**
    * PRIVATE: Internal method - removes "flash" session marked as 'old'
    */
    function _flashdata_sweep()
    {
        foreach ($_SESSION as $name => $value)
        {
            $parts = explode(':old:', $name);
            if (is_array($parts) && count($parts) == 2 && $parts[0] == $this->flashdata_key)
            {
                $this->unset_userdata($name);
            }
        }
    }
} 
[/code]

I hope this post helps you. Have a nice weekend 🙂

ariawan

Web Developer, Blogger, Internet Savvy, Tech Enthusiast

You may also like...

  • Aringmade

    “Second parameter for set_userdata missing.”
    Session bawaan CI ini bikin masalah besar buat aplikasi saya. Sy coba dgn solusi mas ariawan, namun ada pesan kesalahan spt ini:

    “Second parameter for set_userdata missing.”

    Apa ada yg harus dikonfigurasi ulang?

    Ini kode yg sy tuliskan:
    $data=array(
    ‘user_id’=>$ok->id_user,
    ‘user_level’=>$ok->level,
    ‘is_login’ => TRUE

    );
    $this->session->set_userdata($data);

  • hadiariawan

    second parameter yang kurang itu nama session nya..

    $this->session->set_userdata($data,’nama_session’);

  • Rocetudin

    gan ini kan untuk masalah session expired terus ya? klo untuk session yang hanya bisa jalan di browser firefox aja tetapi di browser lain (IE,chrome,safari) session nya malah ga jalan gimana solusinya gan ?

    terima kasih

  • session nya codeigniter itu pake cookies, jadi tiap browser jelas beda. kalo mau yang cross browser gitu ya disimpen di database.