Welcome Guest, Not a member yet? Register   Sign In
Weird twice calling of static function when trying to validate cookies
#1

[eluser]kaluzhanin[/eluser]
Sorry for the awkward name of the topic, I really don't know how to call it :/

So, what I'm trying to implement is "Remember me" checkbox in the login form. If it is set and user provides the right password and login, CI does the following:
1. Create a unique string and stores it in DB table "cookie" in the field "crumble" along with logged user id in the field "user_id" (I use Doctrine, if it's important)
2. Saves the cookie "autologin" on the user's computer with the value of unique string generated on the step 1.

When user requests main controller (/home in my case), CI should do the following:
1. Check if no user is logged in (implemented via singleton class) and there's no cookie to autologin on the user's computer.
2. If step 1 is false, show login form
3. Otherwise show some user control panel.

Checking if there's cookie to autologin is implemented as follows:
1. Current_user class (model) get_cookie with the name autologin.
2. It tries to get user id associated with that cookie from Cookie model via static function getUserID.
3. Cookie::getUserID tries to find() cookie with that value in the database and returns user id associated with that cookie.
4. Current_user gets user id from Cookie and sets that user as current.

It all sounds perfectly sensible (at least for me). But running the code strange things happen: Cookie::getUserID() is somehow called twice in a row, with no parameters in the second call, and everything fails.

Ok, I know you're eager to look at code. Here it is:

Code:
// controllers/home.php, controller to visualize everything
if (Current_User::user() === FALSE && Current_User::cookie_load() === FALSE) {
    $this->load->view('splash_login_form', $data);
} else {
    $data['username'] = Current_User::user()->username;
    $this->load->view('splash_logged', $data);
}

Current_User is implemented as follows:
Code:
// models/current_user.php,
class Current_User {
    private static $user;

    /* here go constructor, login, current user logic, blah-blah, it works fine */

    public static function cookie_load() {
        $crumble = get_cookie('autologin');
        log_message('debug', "cookie_load() crumble: $crumble");
        if ($id = Cookie::getUserID($crumble)) {
            log_message('debug', "cookie_load() User id from crumble: $id");
            if ($u = Doctrine::getTable('user')->find($id)) {
                self::$user = $u;
                                
                $CI =& get_instance();
                $CI->session->set_userdata('user_id', $id);
                
                return TRUE;
            }
        }
        return FALSE;
    }
    
}

Cookie model (it is full, because the way cookies are stored and the structure of the table may be important).

Code:
// models/cookie.php
class Cookie extends Doctrine_Record {
    public function setTableDefinition() {
        $this->hasColumn('user_id', 'integer', 4);
        $this->hasColumn('crumble', 'string', 32);
    }
        
    public function setUp() {
        $this->hasOne('User', array(
            'local'        => 'user_id',
            'foreign'    => 'id'
        ));
    }

    // trying to get user id that has cookie value associated with him.        
    public static function getUserID($crumble) {
        log_message('debug', 'getUserID() is called with crumble ' . $crumble);
        if ($cookie = Doctrine::getTable('cookie')->findOneByCrumble($crumble)) {
            $id = $cookie->User->id;
            log_message('debug', "User id is " . $id);
            return $id;
        }
        return FALSE;
            
    }
        
    // this is how cookies are stored
    public static function storeCrumble($username) {
        $u = Doctrine::getTable('user')->findOneByUsername($username);
        $cookie = Doctrine::getTable('cookie')->findOneByUser_id($u->id);
        if ($cookie === FALSE) {
            $cookie = new Cookie();
            $cookie->user_id = $u->id;
        }
            
        $cookie->crumble = random_string('unique');
        $cookie->save();
        $data = array(
            'name' => 'autologin',
            'value' => $cookie->crumble,
            'domain' => '.mydomain.com',
            'expire' => 60 * 60 * 24 * 365
        );
        set_cookie($data);
    }
}

All right, how do I know that getUserID() is called twice? Log messages tell me so. Here's the excerpt of what I'm getting:

Quote:view/index is calling Current_User::user() and Current_User::cookie_load()
DEBUG - 2010-03-23 13:02:43 --> cookie_load() crumble: 4ac4aeddacd7ef5bfa1b59cf9c9f53ff
DEBUG - 2010-03-23 13:02:43 --> getUserID() is called with crumble 4ac4aeddacd7ef5bfa1b59cf9c9f53ff
DEBUG - 2010-03-23 13:02:43 --> getUserID() is called with crumble 1
DEBUG - 2010-03-23 13:02:43 --> User id is

The funny thing is that if cookie value is wrong (there's no such crumble in database), getUserID() is called only once, according to logs.

I'm stuck, really. May be the answer is very simple, but I'm desperate to find it.
#2

[eluser]kaluzhanin[/eluser]
Silly me. It's not a Codeigniter issue at all. The trouble was in naming getUserID() method - get* methods are magic for Doctrine. Renaming it to _getUserID() worked like a charm. So, a warning to everyone using Doctrine with CI: be more creative :lol:




Theme © iAndrew 2016 - Forum software by © MyBB