如何同步我的用户连接PHP

时间:2014-02-18 18:12:06

标签: php sql synchronization

我在PHP中有一个名为cUser的类:

class cUser {
    var $m_email;//The users email adresse(String)
    var $m_password;//His password(String)
    var $m_username;//His username(String)
    var $m_active;//If the user have been activate (By following a link send to him via is email)(Bool)

    function __construct($p_username, $p_password, $p_email, $p_active) {
        $this->m_username = $p_username;
        $this->m_password = $p_password;
        $this->m_email = $p_email;
        $this->m_active = $p_active;
    }

    //this is the important part...
    function connexion() {
        include "Config.php";//include all the parameters needed to connect to the DB

        $cn = new cConnexion($ConnexionDBHost, $ConnexionDBName, $ConnexionDBLogin, $ConnexionDBPassword);//Initiate a connection to the DB

        if($cn->DBConnexion())//If it is connected {
            $parameters = array('username'=>$this->getUsername(), 'password'=>$this->getPassword());//create an array with the username and the password
            $getConnexion = $cn->SecureSelect("SELECT username, password, email, active FROM user WHERE BINARY username = :username AND BINARY password = :password", $parameters);//selecte the user in the DB (for DB description see below code)

            if($getConnexion != null) { //if there is no error in the query.
                $resultSet = $getConnexion->fetch();//fetch the results
                if($resultSet != null) { //if there is a match
                    //assigne the DB field values to this instance of cUser
                    $this->setUsername($resultSet['username']);
                    $this->setPassword($resultSet['password']);
                    $this->setEmail($resultSet['email']);
                    $this->setActive($resultSet['active']);

                    if($this->getActive() == 1) {
                        //If the user has been activate already return success
                    }
                    else {
                        //Else send an activation email to the user.Dont connecte him and return an error message
                    }
                }
                else {
                    //Send an error message
                }
            }
            else {
                //send an error message
            }
        }
        else {
            //send an error message
        }
    }

    //this are not important for the question but I put them there so you can see what kind of operation the class is doing.
    function delete(){//Delete this instance of cUser from de DB}
    function insert(){//Insert this instance of cUser from the DB}
    function update($p_email, $p_username, ...){//Update this instance of cUser with the new parameters}
    function activateAccount(){//Activate this instance of cUser}
    //And all the getters and setters associate with the class attributes.
}

这是包含cUser类(粗略编码)字段的MySQL表:

USER
    varchar email,
    varchar password,
    varchar username,
    tiny int activate,//1 or 0
    tiny int connected//1 or 0

问题:

如何实现或更改功能连接,以便同时连接一个用户实例?

注意:

我已经知道我可以检查数据库连接字段是否设置为1但是如果两个用户同时访问数据库会产生问题(竞争条件或类似情况)。

我可以使用mutex或信号量来同步连接的DB字段的访问吗?

示例:

David填写HTML表单并使用用户名和密码(“Dav1”,“ThisIsPassword”)提交,一个进程页面创建cUser实例并连接以检查Dav1是否已经存在然后让他访问其余的web应用程序。

现在达沃斯填写表格,并使用与David使用的相同的用户名和密码提交,因为达沃斯和大卫是朋友,他们共享同一个帐户并共享密码。

使用现有代码,David和Davos可以同时使用相同的帐户访问Web应用程序我想要的是当David连接Davos时收到一条错误消息,告诉他用户已经连接或者用户名/密码不匹配。

1 个答案:

答案 0 :(得分:1)

使用交易。

在MySql中,您还可以使用SELECT FOR UPDATE语句。

<强>伪代码:

$transaction = db->beginTransaction();
try {
    $user = User::getByUsername($username);

    if ($passwordImcorrect)
        throw new Exception('invalid credentials');

    if (user->loggedIn)
        throw new Exception('already logged in');

    user->loggedIn = 1;
    user->save();

    $transaction->commit();
}
catch (Exception $e) {
    echo $e->getMessage();
    $transaction->rollback();
}