我在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时收到一条错误消息,告诉他用户已经连接或者用户名/密码不匹配。
答案 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();
}