这是使用两个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)");
}
我确信有更好的方法可以做到这一点。这就是为什么我希望有人可以帮助我:)。
提前感谢所有回复
答案 0 :(得分: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循环,那么两个数组所需的最小循环量必须是两个。数组是UNRELATED所以你不能使用它来更容易解析另一个。
使用
解析$ overTimeHours$overTimeHours as $key => $value
假设您确实需要数组中的键和值,这是您可以做的最短的事情。 lieuTimeHours也是如此。
不要在您的查询中插入变量,如下所示:
SET lieu_hours='$value2'
一个体面的程序员(或一个12岁的孩子)可以轻松地将这样的东西输入你的数据库:
yo';DROP TAbLE users;--
或者类似的东西,从数据库中删除数据。您必须使用预准备语句,以防止受到基本SQL注入的攻击。</ p>
预备语句在大多数情况下都可用,但我强烈建议使用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注入(不同之处在于:未准备的查询运行命令,同时准备好的查询是纯粹的STRINGS):
$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
}
另外我注意到我添加了一个“;”在您的脚本结束时,这不是必须的,但我觉得更安全,确保告诉您的执行已经完成,并且您不希望任何相关内容跟随(即使它不是来自您)。
我希望我回答你的问题(并希望超越这个问题),我希望你会考虑我说的话:)随意询问是否有任何问题。
另外,如果我在写这个答案时可能说错了,请不要犹豫纠正我。
答案 1 :(得分:2)
适用于您的情况,以下是经过调整的answer of 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
?>
答案 2 :(得分: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);
}
答案 3 :(得分:1)
在我看来,你要做的第一件事就是减少与DB打开连接的次数,如下所示:
$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);
第二,重要的是,就像你说的那样在一次尝试中组合两个数组并调试你的代码,直到你成功。