检查用户是否存在。

6

可能是重复问题:
Phonegap - Load Values from Database based on a user ID

我正在创建一个需要用户注册的Phonegap应用程序。我通过一个作为Web服务的PHP脚本连接MySQL数据库,并使用AJAX POST/Get方法进行操作。

但无论什么原因,LogCat总是给我返回"There was an error"(在post的错误函数中)。

更新: 从MySQL的日志中,我得到了这个错误信息:
PHP致命错误:调用非对象的成员函数bindValue()
它指向这一行:$username = $_POST['username'];

以下是我JS代码的片段:

var u = $("#username").val();    
var p = $("#password").val();

var userRegData = $('#registration').serialize();

$.ajax({
  type: 'POST',
  data: userRegData,
  dataType: 'JSONp',
  url: 'http://www.somedomain.com/php/userregistration.php',
  success: function(data){   
      if(response==1){
          // User can be saved
      } else {
          // User exsts already 
      }
  },
  error: function(e){
      console.log('There was an error');
      $.mobile.loading ('hide'); 
  }
}); 
return false;

这是我的 PHP 代码片段。我正在使用 PDO。

$db = new PDO('mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'], $config['db']['username'], $config['db']['password']);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$username = $_POST['username'];
$password = $_POST['password'];
$query->bindValue(':username', $username, PDO::PARAM_STR);
$query->bindValue(':password', $password, PDO::PARAM_STR);

try {

$db->beginTransaction();

$db->query("SELECT `user`.`Username` FROM `user` WHERE `user`.`Username` = :username LIMIT 1");
try {
    if ( $query->rowCount() > 0 ) {
        $response=1;
        echo $response;
    }
    else {
        $response=0;
        $db->query("INSERT INTO `user` (`user`.`Username`, `user`.`Password`) VALUES :username, :password");
        echo $response; 
        $db->commit();  
    }
} catch (PDOException $e) {
    die ($e->getMessage());
}


} catch (PDOException $e) {
    $db->rollBack();
    die ($e->getMessage());
}

你应该检查浏览器的XHR(Ajax)控制台,查看后端返回的内容。错误必须在后端而不是前端。另一种调试方法是在后端硬编码POST值并查看错误信息。 - Blaise
你可以尝试使用console.log(e)来代替console.log('There was an error'),然后请告诉我们输出结果。 - T.Baba
@Hvandracas 这是我第一次使用PDO,所以我不确定我的代码结构是否正确。你有使用PDO的经验吗?你觉得我写的逻辑有意义吗? - user1809790
bindValue只能在已经准备好的语句上使用,而你没有准备好任何语句 :) - Ja͢ck
1
FYI,您不需要在所有列名前面使用表名。除非它们是保留关键字,否则大多数列名也不需要使用反引号。 - ThiefMaster
显示剩余3条评论
4个回答

1

应该是这样的

您的HTML页面

<html>
    <body>
        <script>
            function checkIfUserCanBeSaved(){
                var userRegData = $('#registration').serialize();

                $.ajax({
                  type: 'POST',
                  data: userRegData,
                  url: 'http://www.somedomain.com/php/userregistration.php',
                  success: function(data){   
                      if(response==1){
                          alert('user found');
                      } else {
                          alert('user saved')
                      }
                  },
                  error: function(e){
                      console.log('There was an error');
                      $.mobile.loading ('hide');
                  }
                });
                return false;
            }
        </script>
        <form id="registration">
            <input type="text" name="username">
            <input type="text" name="password">
            <input type="button" onclick="checkIfUserCanBeSaved()" value="submit">
        </form>
    </body>
</html>

您的PHP页面
$db = new PDO('mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'], $config['db']['username'], $config['db']['password']);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$username = $_POST['username'];
$password = $_POST['password'];


try {

$db->beginTransaction();

try {

     $query = $db->prepare("SELECT user.Username FROM user WHERE user.Username = :username LIMIT 1");
     $query->bindValue(':username', $username, PDO::PARAM_STR);
     $query->execute();

    if ( $query->rowCount() > 0 ) {
        $response=1;
        echo $response;
    }
    else {
        $response=0;
        $query = $db->prepare("INSERT INTO user ( username, password ) VALUES ( :username, :password )" );
        $query->bindValue(':username', $username, PDO::PARAM_STR);
        $query->bindValue(':password', $password, PDO::PARAM_STR);
        $query->execute();
        echo $response; 
        $db->commit();  
    }
} catch (PDOException $e) {
    die ($e->getMessage());
}


} catch (PDOException $e) {
    $db->rollBack();
    die ($e->getMessage());
}

由于我正在检查数据库中的值,然后实际插入,这应该被视为JS中的POST还是GET? - user1809790
由于您使用了类型为“POST”的Ajax请求,使用$_POST['username']应该能够工作。 对于此类请求使用POST也比GET更好。 - Akash
我已经更新了我的答案,附上了HTML代码,请告诉我这是否有效。 - Akash
请确保您发布的URL是有效的,并且您可以直接访问该URL,如果出现超时错误,则通常会发生此类错误。 - Akash
让我们在聊天中继续这个讨论 - user1809790
显示剩余9条评论

1

这里有两个基本问题:您不了解JSONP的限制,并且您正在错误地使用PDO。

PDO

有几种PDO使用模式。(您可以为清晰度和代码重用抽象这些模式,但基本上必须按照以下顺序使用对象。)

简单查询

// 1. Get a database handle
$dh = new PDO($DSN, $USERNAME, $PASSWORD, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

// 2. Issue a string query, no bindings!
$cursor = $dh->query('SELECT 1');

// 3. read results. There are many ways to do this:
// 3a. Iteration
foreach ($cursor as $row) {
    //...
}

// 3b. *fetch*
// You can use any one of multiple fetch modes:
// http://php.net/manual/en/pdostatement.fetch.php
while ($row = $cursor->fetch()) {
    //...
}

// 3c. *fetchAll*
//     *fetchAll* can also do some aggregation across all rows:
//     http://php.net/manual/en/pdostatement.fetchall.php
$results = $cursor->fetchAll();

// 3d. *bindColumn*
$cursor->bindColumn(1, $id, PDO::PARAM_INT);
while ($cursor->fetch(PDO::FETCH_BOUND)) {
    //$id == column 1 for this row.
}

// 4. close your cursor
$cursor->closeCursor();

预处理语句

// 1. Get a database handle
$dh = new PDO($DSN, $USERNAME, $PASSWORD, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

// 2. Prepare a statement, with bindings
$cursor = $dh->prepare('SELECT id, name FROM mytable WHERE name = :name');

// 3. Bind parameters to the statement. There are three ways to do this:
// 3a. via *execute*:
$cursor->execute(array(':name'=>$_GET['name']));

// 3b. via *bindValue*
$cursor->bindValue(':name', $_GET['name']);

// 3c. via *bindParam*. In this case the cursor receives a *reference*.
$name = 'name1';
$cursor->bindParam(':name', $name); // name sent to DB is 'name1'
$name = 'name2'; // name sent to DB is now 'name2'!
$name = 'name3'; // now it's 'name3'!

// 4. Execute the statement
$cursor->execute();

// 5. Read the results
//    You can use any of the methods shown above.

foreach ($cursor as $row) { // Iteration
    // ...
}

// 6. Don't forget to close your cursor!
//    You can execute() it again if you want, but you must close it first.

$cursor->closeCursor();

JSONP

你的代码中还有许多其他问题,这似乎是因为你不清楚在浏览器和服务器之间传输什么。

JSONP是一种绕过浏览器跨域请求限制的技术。它通过向当前页面添加一个带有URL和callback=查询参数的


虽然我已经达到了投票限制,但是精神上我还是支持你的。如果你已经在建议使用crypt()函数,那么你应该使用bcrypt($2y$)函数。 - Ja͢ck
我是PHP的新手,尝试了您的代码,尽管我本来必须完全改变我的逻辑。我知道您的代码更安全、更专业,但我只是在做演示,并不需要这样的安全性。我还使用sha1()将密码保存在数据库中。 - user1809790
使用像MD5或SHA1这样的简单哈希,即使加盐,也几乎和明文密码一样糟糕。如果甚至PHP文档告诉你它不安全,那就说明了问题。然而,我建议的代码的重点不是安全性,而是接口的清晰度和对RESTful原则的遵守。 - Francis Avila

0

serialize方法的作用是将您的变量转换为JSON数组,我假设您没有给输入命名。因此,您应该在HTML中放置名称,类似于以下内容:

<form id="registration">
    <input type="text" name="username" ... 
    <input type="password" name="password" ...

现在当您运行代码时,userRegData将会是以下内容:

username=value_in_username_input&password=value_in_password_input

我已经有了名称,当我尝试使用alert($('#registration').serialize());时,我得到了你给我的相同字符串。我不确定发生了什么,因为当我按下ok时,什么也没有发生-它转而进入错误函数而不是成功函数。 - user1809790
序列化的形式如下:username=用户名中的值&password=密码中的值&password-check=密码检查中的值 - user1809790
还有一件事可尝试,您能转储POST变量吗?让我们看看输出结果。 - T.Baba

0

这应该会更有帮助,您还需要修改您的SQL语句。问题在于您使用了两种不同的查询方法。绑定参数需要使用Prepare语句。

$username = $_POST['username'];
$password = $_POST['password'];
//new query
$query = $db->prepare("SELECT `user`.`Username` FROM `user` WHERE `user`.`Username` = :username LIMIT 1");
// since you're only using one argument, the password in the prior query I did not bind this here.
$query->bindParam(':username' PDO::PARAM_STR);

try {

$db->execute();

我需要先使用SELECT语句检查用户是否存在于数据库中,如果用户不存在,则触发INSERT语句。这就是为什么我的代码中有两个语句的原因。然而,我不确定这是否是正确的做法。 - user1809790

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接