当名称包含撇号时,用于匹配通过表单提交的名称与MySQL数据库中断的脚本

时间:2011-11-01 17:22:33

标签: php mysql forms mysql-real-escape-string apostrophe

我有使用mysql_real_escape_string将名称输入MySQL数据库的脚本,以便正确处理撇号。我遇到的麻烦是使用下面的脚本检查是否使用另一个表单输入的名称对应于我的数据库中已有的名称,如果找到名称则更新该行。

当我尝试在此脚本处理的表单中输入带有撇号的名称时,我收到一条错误消息,指出未找到该名称,并且错误消息中的名称在撇号之前包含反斜杠,显然是个问题。

所以问题是,我如何修改下面的脚本,以便它可以与带有撇号的名称一起使用?

谢谢,

尼克

$row_count = count($_POST['name']);
if ($row_count > 0) {

    mysql_select_db($database, $connection);
    $name = array();
    $workshop = array(); 
    $not_found = array();

    for($i = 0; $i < $row_count; $i++) {
        // variable sanitation...
        $name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
        $workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
    }
    $names = "('".implode("','",$name)."')";

    $not_in = Array();

    // lets say all names doesn't exist in `conference`
    foreach($name as $value) {
        // names in array are keys, not values
        $not_in[$value] = true;
    }


    $query = mysql_query("SELECT Name FROM conference WHERE Name IN $names"); 
    while(list($dbname) = @mysql_fetch_row($query)) {
        // delete those name from $not_in who exists
        unset($not_in[$dbname]);
    }

    // names in $not_in array are keys, not values
    $not_in = array_keys($not_in);

    if(empty($not_in)) {
        // its ok, all names have been found. do the magic.
        for($i = 0; $i < $row_count; $i++) {
            $sql = "UPDATE conference SET Workshop = '$workshop[$i]' WHERE Name LIKE '$name[$i]'";
            mysql_query($sql);
            $body .= "Name: " . $name[$i] . "    Workshop: " . $workshop[$i] . "\n\n";
        }

1 个答案:

答案 0 :(得分:1)

嗯!我想我可能已经找到了这个问题。问题可能不在于查询,而在于PHP代码。我将尝试使用您的示例John O'Shea来解释下面。

for($i = 0; $i < $row_count; $i++) {
    // variable sanitation...
    $name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
    $workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
}
$names = "('".implode("','",$name)."')";

$not_in = Array();

// lets say all names doesn't exist in `conference`
foreach($name as $value) {
    // names in array are keys, not values
    $not_in[$value] = true;
}

在上面的代码之后,Array $ not_in将包含转义键,因为$ name已经包含使用mysql_real_escape_string()转义的值。因此,例如:

$ not_in [John] = true; $ not_in [John O \'Shea] = true;

$query = mysql_query("SELECT Name FROM conference WHERE Name IN $names"); 
while(list($dbname) = @mysql_fetch_row($query)) {
    // delete those name from $not_in who exists
    unset($not_in[$dbname]);
}

现在上面代码中的$ dbname包含从DB检索到的非转义值,例如没有反斜杠的John O'Shea。由于这不是$ not_in包含的内容,因此unset()将不起作用。这意味着所有撇号值都保留在$ not_in数组中。

所以修复是将未转义的值保存在$ not_in。

希望这是有道理的!

==========编辑:回应如何在$ not_in中保留未转义的值:

我们的想法是在需要的地方进行转义。以下是您可能对代码所做的更改:

重写第一个for(),如下所示:

for($i = 0; $i < $row_count; $i++) {
    // variable sanitation...
    //$name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
    $name[$i] = ucwords($_POST['name'][$i]);
    $workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
}
$names = "('" . mysql_real_escape_string(implode("','",$name)) . "')";

将UPDATE语句重写为:

$sql = "UPDATE conference SET Workshop = '$workshop[$i]' WHERE Name LIKE '" . mysql_real_escape_string($name[$i]) . "'";

顺便说一句,根据您的代码,如果数据库中不存在一个名称,则UPDATE将不会运行。仅当在数据库中找到所有$ _POST ['name']时,是否必须运行UPDATE?如果没有,您可以大大减少代码量。

我没有测试过上述更改,但我认为它们应该可行。如果您遇到任何问题,请告诉我。

==========编辑2:用于更新存在的记录并为未记录的记录生成错误的代码片段

嘿尼克,我认为只编写下面的代码应该可以解决问题:

$row_count = count($_POST['name']);
if ($row_count > 0) {
    mysql_select_db($database, $connection);
    for ($i = 0; $i < $row_count; $i++) {
        mysql_query("UPDATE conference SET Workshop = '" . mysql_real_escape_string($_POST['workshop'][$i]) . "' WHERE Name LIKE '" . mysql_real_escape_string($_POST['name'][$i]) . "'");
        $affectedRows = mysql_affected_rows();
        if ($affectedRows == 0) {
            echo '<br>Name did not exist - ' . $_POST['name'][$i];
        }
    }
}

希望这有帮助!