【问题标题】:Correct PDO Syntax for Updating an Array of primary keys.更新主键数组的正确 PDO 语法。
【发布时间】:2015-05-26 14:31:31
【问题描述】:

嗨_我正在尝试在我的 Facebook Canvas 游戏中发生特定事件时在我的数据库上运行 PDO 更新,但我的语法遇到了一些困难,希望有人能提供帮助。

我有一个名为Balance 的表。此表包含以下列:facebookIDgoldbalanceinvite。 此表存储每个玩家的金币余额,invite 列记录该玩家是否向其他玩家发送了成功(接受)的游戏邀请。

我目前正在做的是:当有新玩家加入游戏时,我会在 Facebook 的 Graph API 上运行检查以查看哪些(如果有)其他玩家邀请了这个新玩家,如果有,然后我抓住他们的ID然后做一个AJAX帖子将它们发送到一个PHP文件,我想奖励这些玩家的goldbalance +100金币,我还想将他们的invite列从0更改为1(这将导致显示一个弹出窗口,在他们下次登录游戏时通知他们奖励)。

现在我成功地将邀请发件人的 ID 作为数组发送到我的 PHP 文件中,但是我无法成功地对玩家的金币余额进行 PDO 更新。

这是我的 AJAX 代码,它以数组的形式发送 ID:

// requestid is the Array containing the sender IDs
   $.ajax({
    url: 'scripts/requestreward.php',
    data: {'requestid' : requestid},
    type: "POST",
    success: function(response){

        alert(response);
                }
   });

这是我当前的 PDO PHP 文件:

<?php

$servername = myservername;
$username = myusername;
$password = mypassword;
$dbname = mydbname;

//Create connection:
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $conn->prepare("UPDATE `Balance` 
SET `goldbalance` = `goldbalance` + 100,
`invite` = 1,
WHERE `facebookID` = :requestId,

foreach($_POST['requestid'] as $requestId){
`facebookID`="($requestId)"; }");

$stmt->bindParam(':requestid', $requestid);
$requestid = $_POST['requestid'];
$stmt->execute();

$conn->commit();
echo "Success";
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>

我一直在尝试将其作为一个准备好的 PDO 语句来执行,因为我已经读过它更安全,但我很确定我为数组中的每个项目执行了不正确的更新循环。

另外,我不确定这条线是否是将玩家的金币余额(即 INT)增加 100 的正确方法:SET `goldbalance` = `goldbalance` + 100,

非常感谢您提供任何帮助,在此先感谢您!

【问题讨论】:

  • 该代码完全是错误的。您的 SQL 未以悬空的, 和缺少的"); 终止,并且仍然容易受到sql injection attacks 的攻击。

标签: php arrays ajax pdo prepared-statement


【解决方案1】:

您的语法不是有效的 PHP 语法。您不能只在字符串中创建 foreach

使用占位符编写语句,然后遍历所有 requestId 以根据需要多次执行语句。

看看这段代码,它应该可以按你的意愿工作。

try {
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // set the PDO error mode to exception
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $conn->prepare("UPDATE `Balance` 
    SET `goldbalance` = `goldbalance` + 100,
    `invite` = 1
    WHERE `facebookID` = :requestId");

    $stmt->bindParam(':requestId', $requestId);

    foreach($_POST['requestid'] as $r) { 
        $requestId = $r;
        $stmt->execute();
    }

    echo "Success";
}
catch(PDOException $e)
{
    echo "Error: " . $e->getMessage();
}

此外,您的$con-&gt;commit() 没有用,因为您没有开始交易。

安全注意事项

正如 Marc B 在 cmets 上所说,您的代码容易受到 SQL 注入的攻击。在将数据用于查询之前,您应该了解如何从用户输入中清理数据。

【讨论】:

  • bindParam应该在foreach之外(因为绑定的是引用而不是值,所以不需要绑定多次):$stmt-&gt;bindParam(':requestid', $requestId); foreach($_POST['requestid'] as $requestId) { $stmt-&gt;execute(); }
  • 感谢您指出这一点,我习惯使用bindValue()。我更正了。
  • 嗨@Mr.Blackus 感谢您的回复!我正在尝试您的代码,但它给了我这个错误消息:Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE `facebookID` = '107263943372127'' at line 4 你知道可能出了什么问题吗?再次感谢。
  • 您好 @Mr.Blackus 原来是 ``invite` = 1,`` 末尾的逗号导致了错误,现在一切正常,再次感谢!我想知道,在安全方面,这段代码是否仍然容易受到 SQL 注入的影响?由于传递给它的数据(ID)直接来自 Facebook 的 API,是否仍然存在注入攻击的风险?
  • 哎呀,错过了,我更正了。嗯,事实上,当您使用bindParam() 时,应该保护您免受 SQL 注入。说得太快了。但是您应该在使用之前检查 $_POST 变量上的内容。至少对于格式。它应该是一个数组,但你永远不会检查它。不是安全问题,但如果是其他问题,您的代码会发出警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 2018-12-11
相关资源
最近更新 更多