2

这是将两个foreach语句与进入 MySQL 数据库的数组一起使用的唯一方法吗?

第一个将更新ot_hours字段,第二个foreach将更新lieu_hours字段。我试图将两者结合起来做一个查询,但它不断更新错误的值。

这就是我现在所拥有的,但很丑陋。

foreach($_POST['overtimehours'] as $key => $value) { 
    dbQuery("UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)");
}
foreach($_POST['lieutimehours'] as $key2 => $value2) {
    dbQuery("UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)");
}

我确信有更好的方法来做到这一点。这就是为什么我希望有人可以帮助我:)

提前感谢所有回复

4

4 回答 4

2

至少你愿意学习新事物,这很好。

  • 不要假设您希望发布的所有内容实际上都已发布。

使用三元运算和 isset 函数来检查您的帖子是否真的到位:

$overTimeHours = isset($_POST['overtimehours']) ? $_POST['overtimehours'] : false;
$lieuTimeHours = isset($_POST['lieutimehours']) ? $_POST['lieutimehours'] : false;
if($overTimeHours != false && $lieuTimeHours != false)
{
    // Proceed ; checkpoint #1
}
else
{
    // The values were not posted, do some error handling.
}

因此,此时,在检查点 #1 内,您将执行以下操作:

foreach($overTimeHours as $key => $value)
{ 
    dbQuery("UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)");
}
foreach($lieuTimeHours as $key2 => $value2)
{
    dbQuery("UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3)");
}
  • 如果您只有一个要解析的数组,您可能不会觉得运行一个 for 循环很难看。

现在你有两个数组(显然),所以如果一个数组的最小循环量是一个 for 循环,那么你需要的两个数组的最小循环量必须是两个。这些数组是不相关的,因此您不能使用其中一个来更轻松地解析另一个数组。

通过 $overTimeHours 解析

$overTimeHours as $key => $value

假设您确实需要数组中的键和值,这是您可以做的最短的事情。同样的故事也适用于lieuTimeHours

  • 您的代码很容易受到 SQL 注入的影响。

不要像这样在查询中插入变量:

SET lieu_hours='$value2'

一个体面的程序员(或者一个 12 岁的孩子)可以很容易地在你的数据库中输入这样的内容:

yo';DROP TAbLE users;--

或类似的东西,从数据库中删除数据。您必须使用准备好的语句以防止受到基本 SQL 注入的攻击。

准备好的语句在大多数情况下都可用,但我强烈建议使用 PDO 或 mysqli 语法。

以下是如何创建 PDO 连接的示例:

// Usage:   $db = connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword);
// Pre:     $dbHost is the database hostname, 
//          $dbName is the name of the database itself,
//          $dbUsername is the username to access the database,
//          $dbPassword is the password for the user of the database.
// Post:    $db is an PDO connection to the database, based on the input parameters.
function connectToDatabase($dbHost, $dbName, $dbUsername, $dbPassword)
{
    try
    {
         return new PDO("mysql:host=$dbHost;dbname=$dbName;charset=UTF-8", $dbUsername, $dbPassword);
    }
    catch(PDOException $PDOexception)
    {
        exit("<p>An error ocurred: Can't connect to database. </p><p>More preciesly: ". $PDOexception->getMessage(). "</p>");
    }
}

现在您可以初始化数据库变量:

$host = 'localhost';
$user = 'root';
$databaseName = 'databaseName';
$pass = '';

现在您可以通过以下方式访问您的数据库

$db = connectToDatabase($host, $databaseName, $user, $pass); // You can make it be a global variable if you want to access it from somewhere else.

现在您可以创建一个接受准备好的语句的查询:

$query = "UPDATE :table SET ot_hours=:ot_hours, ot_status=1, ot_submitdate=:ot_submitdate WHERE trans_num=:key AND uid=:contextUser AND (ot_status=0 OR ot_status=1 OR ot_status=3);";

现在您可以轻松地准备它,将变量执行到查询中,而无需使用 sql 注入(区别在于:未准备好的查询运行命令,而准备好的查询是纯字符串):

$statement = $db->prepare($query); // Prepare the query.
$success = $statement->execute(array(
    ':table' => $TABLE,
    ':ot_hours' => $ot_hours,
    ':ot_submitdate ' => $ot_submitdate ,
    ':key' => $key,
    ':contextUser' => $contextUser
)); // Here you insert the variable, by executing it 'into' the prepared query.

if($success)
{
    // Update was successful.
]
else
{
    // Update was not successful, feel free to catch an PDOException $PDOexception
}

我还注意到我添加了一个“;” 在你的脚本的末尾,这不是必需的,但我觉得它更安全,确保告诉你你的执行已经完成并且你不想要任何与后续相关的东西(即使它不是来自你)。

我希望我回答了您的问题(并希望超出此范围),我希望您会考虑我所说的:) 如果有任何问题,请随时提问。

另外,如果我在写这个答案时可能说错了什么,请不要犹豫纠正我。

于 2013-04-15T19:50:48.507 回答
2

适用于您的情况,这是 Danny 的改编答案

<?php

//first query:
$arrk = array_keys($_POST['overtimehours']);
$arrv = array_values($_POST['overtimehours']);
$id_list = implode(',', $arrk);

$whens = implode(
    "\n    ",
    array_map(
        function ($id, $value) {
            return "WHEN {$id} THEN {$value}";
        },
        $arrk,
        $arrv
    )
);

$sql1 = "
    UPDATE $TABLE
    SET ot_hours = CASE trans_num
    {$whens}
    END,
    ot_status=1, 
    ot_submitdate='$ot_submitdate'
    WHERE id IN ({$id_list})
    AND uid='$contextUser' 
    AND (ot_status=0 OR ot_status=1 OR ot_status=3) 
";

//second query:
$arrk = array_keys($_POST['lieutimehours']);
$arrv = array_values($_POST['lieutimehours']);

$id_list = implode(',', $arrk);

$whens = implode(
    "\n    ",
    array_map(
        function ($id, $value) {
            return "WHEN {$id} THEN {$value}";
        },
        $arrk,
        $arrv
    )
);

$sql2 = "
    UPDATE $TABLE
    SET lieu_hours = CASE trans_num
    {$whens}
    END,
    ot_status=1, 
    ot_submitdate='$ot_submitdate'
    WHERE id IN ({$id_list})
    AND uid='$contextUser' 
    AND (ot_status=0 OR ot_status=1 OR ot_status=3) 
";

//now use pdo to run sql1 and sql2

?>
于 2013-04-15T20:21:38.303 回答
1

我建议您使用准备好的语句。您至少应该正确编码您使用的其他变量 ( $TABLE, ...)

$firstUpdate = 
    "UPDATE $TABLE 
        SET ot_hours=:value, ot_status=1, ot_submitdate='$ot_submitdate' 
      WHERE trans_num=:key 
        AND uid='$contextUser' 
        AND (ot_status=0 OR ot_status=1 OR ot_status=3)";

 $secondUpdate =
     "UPDATE $TABLE 
         SET lieu_hours=':value', ot_status=1, ot_submitdate='$ot_submitdate' 
       WHERE trans_num=:key 
         AND uid='$contextUser' 
         AND (ot_status=0 OR ot_status=1 OR ot_status=3)";

$db = PDO(...); // I assume here a connection managed by PDO

$stmt = $db->prepare($firstUpdate);
foreach($_POST['overtimehours'] as $key => $value) {
      $stmt->execute(array(":key"=>$key,":value"=>$value);
}

$stmt = $db->prepare($secondUpdate);
foreach($_POST['lieutimehours'] as $key => $value) {
        $stmt->execute(array(":key"=>$key,":value"=>$value);
}
于 2013-04-15T19:37:44.353 回答
1

在我看来,您要做的第一件事是减少打开与数据库的连接的次数,如下所示:

$query = "";
foreach($_POST['overtimehours'] as $key => $value) { 
    $query .="UPDATE $TABLE SET ot_hours='$value', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3) ; ";
}
foreach($_POST['lieutimehours'] as $key2 => $value2) {
    $query .= "UPDATE $TABLE SET lieu_hours='$value2', ot_status=1, ot_submitdate='$ot_submitdate' WHERE trans_num=$key2 AND uid='$contextUser' AND (ot_status=0 OR ot_status=1 OR ot_status=3); ";
} 
if ($query)  dbQuery($query);

其次,这很重要,就像您所说的一次尝试将两个数组组合在一起并调试您的代码,直到您成功为止。

于 2013-04-15T19:40:28.413 回答