Php 在嵌套循环中从Post中剥离值
我有一个用于动态构建更新查询的函数,该函数使用手动创建的表单,表单中的字段与表列的名称匹配,然后基于提交的字段名称和值构建查询。然而,我遇到了一个实例,其中某些已发布的字段必须过滤掉。如果手动操作,我可以很容易地完成这项工作,但我正试图在需要删除的列数(作为数组输入)不一定事先知道的情况下使其工作 例如,如果我用它来代替下面的一个foreach循环,它会起作用:Php 在嵌套循环中从Post中剥离值,php,forms,loops,foreach,Php,Forms,Loops,Foreach,我有一个用于动态构建更新查询的函数,该函数使用手动创建的表单,表单中的字段与表列的名称匹配,然后基于提交的字段名称和值构建查询。然而,我遇到了一个实例,其中某些已发布的字段必须过滤掉。如果手动操作,我可以很容易地完成这项工作,但我正试图在需要删除的列数(作为数组输入)不一定事先知道的情况下使其工作 例如,如果我用它来代替下面的一个foreach循环,它会起作用: $FieldName = array_values($Date1Name); // Remove $Date1Name submit
$FieldName = array_values($Date1Name);
// Remove $Date1Name submit values
if ($key == $FieldName[1]) continue;
if ($key == $FieldName[2]) continue;
if ($key == $FieldName[3]) continue;
但是我尝试动态地做它,如下所示。注意,在这种情况下,数组的第一个值不能删除,因为它是实际的字段名,但在第二个foreach循环中,所有值都要删除。有什么想法吗
function formProcess($ID,$DBName,$TableName,$PassName,$Date1Name,$Date2Name,$RemoveFields,$insertGoTo) {
$Values = array();
// Update record
if (isset($_POST["update"])) :
unset($_POST['update']);
foreach ($_POST as $key=>$value ) :
if (is_array($Date1Name)) :
// ARRAY EXAMPLE
//$Date1Name = array("StartDate","month1","day1","year1");
$Field1Name = array_values($Date1Name);
foreach($Date1Name as $keyrm) :
if ($keyrm !== 0 && $key == $Field1Name) continue;
endforeach;
endif;
if (is_array($RemoveFields)) :
// Remove certain fields from POST using $RemoveFields array values
// ARRAY EXAMPLE
//$RemoveFields = array("ID","EndName");
$FieldRemoved = array_values($RemoveFields);
foreach($RemoveFields as $keyrm) :
if ($keyrm == $FieldRemoved) continue;
endforeach;
endif;
$Values[] = "`$key`=".isNull($value, $DBName);
endforeach;
$sqlUpdate = "UPDATE $TableName SET ".implode(",",$Values)
." WHERE ID='".intval($ID)."'";
DBConnect($sqlUpdate, "Update", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo."?ID=".intval($ID)));
endif;
endif;
}
我过去也做过类似的工作,也许它会给你一些想法。这是假设您使用的是mysql,如果不是,过滤器可能需要某种程度的手动处理 1创建一个从表中提取字段的函数。我有一个被标记为$db的类。它将运行我的查询并返回关联数组:
function getFields($table,$db)
{
# Run the "describe table" query
$fields = $db->query("describe {$table}")->getResults();
# Extract just the field names from the rows
foreach($fields as $row) {
$val[] = $row['Field'];
}
# Send back the field names
return $val;
}
下面是上述函数将在简单用户表上返回的内容:
2接下来创建过滤函数。我也会发回一个绑定数组,我在这里使用PDO作为我的终端数据库,不确定您使用的是哪个库
function filterArray($array,$filter = array())
{
$bind =
$cols = array();
if(!is_array($filter))
$filter = array();
foreach($array as $key => $value) {
if(!empty($filter) && !in_array($key, $filter))
continue;
$bKey = ":{$key}";
$bind[$bKey] = $value;
$cols[] = $key;
}
return array(
'columns'=>$cols,
'bind' => $bind
);
}
3.设置更新功能。我已经把它简单化了,你可以根据需要把它复杂化
# The first is the filtered array, the $where is which key to update on,
# the $table is obvious, the $op is the operator which could be substituted for
# LIKE or !=
function getUpdateStatement($array,$where,$table,$op = '=')
{
# Start off the statement
$sql['update'][] = "UPDATE {$table} SET";
# Combine and loop the keys/values and assign the WHERE anchor as well
foreach(array_combine($array['columns'],array_keys($array['bind'])) as $col => $bind) {
if($col == $where)
$sql['where'][] = "WHERE `{$col}` {$op} {$bind}";
else
$sql['cols'][] = "`{$col}` = {$bind}";
}
# Create the statement from the parts
$statement = implode(' ',$sql['update']).' '.implode(", ",$sql['cols']).' '.implode(" AND ",$sql['where']);
# Send back statement
return $statement;
}
使用:
# Get all the columns from the table
$filter = getFields('users',$queryEngine);
# Let's pretend the is a actually your $_POST array...
$POST = array(
'ID' => 123,
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'test@best.com',
'update' => 'SAVE',
'action' => 'update_my_stuff',
'token' => 'aB23As753hedD6baC213Dsae4'
);
# Create the filtered array
$filtered = filterArray($POST,$filter);
# Create the statement
echo getUpdateStatement($filtered,'ID','user');
上述声明内容如下:
UPDATE users SET `first_name` = :first_name, `last_name` = :last_name, `email` = :email WHERE `ID` = :ID
记住绑定值在$filtered['bind']数组中。希望这就是您正在寻找的,或者它可能会给您一些想法。现在就开始工作,并进行更新以处理插入、更新和删除操作。由于需要一些特殊的字段处理,我决定不能为更新和插入查询构建单独的函数,因此我将该功能移回主formProcess函数。我确实需要过滤掉某些字段,而不是说要保留哪些字段,所以我想出了一种方法,使用array_diff_key和array_flip的组合来实现这一点,这似乎很管用。这将提供所有要处理的字段的数组。这样做的主要原因是过滤掉日、月和年选择器,然后将它们处理到单个字段中: $filteredarray=array\u diff\u key$\u POST,array\u flip$RemoveFields 我相信这里的一些程序员确实可以简化这段代码,但这里的注释说明了它的作用。我希望它能帮助别人
function formProcess($ID,$DBName,$TableName,$PassName,$Date1Name,$Date2Name,$RemoveFields,$insertGoTo) {
// Insert record
if (isset($_POST["insert"])) :
unset($_POST["insert"]);
// Remove unneeded fields from $RemoveFields variable
if (!is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
// Build the INSERT query
foreach($filteredarray as $col => $val) :
// Process Password field
if ($PassName) :
// Encode password field
if ($col == $PassName && $val != "") $val=md5($val);
// If no changes, save original password
if ($col == $PassName && $val == "") continue;
endif;
// Process Date/Time fields using custom dateProcess()
if (is_array($Date1Name)) :
$pieces1 = $Date1Name;
if ($col == $pieces1[0]) $val = dateProcess($Date1Name);
endif;
if (is_array($Date2Name)) :
$pieces2 = $Date2Name;
if ($col == $pieces2[0]) $val = dateProcess($Date2Name);
endif;
$Fields[] = "`$col`";
$Values[] = isNull($val, $DBName);
endforeach;
$sqlInsert = "INSERT INTO $TableName (".implode(",",$Fields).")
VALUES (".implode(",",$Values).")";
// Custom function to process the INSERT query
$InsertID = DBConnect($sqlInsert, "Insert", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo."?ID=".intval($InsertID)));
endif;
// Update record
elseif (isset($_POST["update"])) :
unset($_POST['update']);
// Remove unneeded fields using array $RemoveFields variable
if (!is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
// Build the UPDATE query
$count = 0;
$fields = '';
$Where = '';
foreach($filteredarray as $col => $val) :
if ($count++ != 0 && $col != "ID") $fields .= ', ';
if ($col == "ID") :
$Where = " WHERE `$col` = " . intval($val);
else :
// Process Password field
if ($PassName) :
// Encode password field
if ($col == $PassName && $val != "") $val=md5($val);
// If no changes, save original password
if ($col == $PassName && $val == "") continue;
endif;
// Process Date/Time fields
if (is_array($Date1Name)) :
$pieces1 = $Date1Name;
// Process first Date/Time field using custom function
if ($col == $pieces1[0]) $val = dateProcess($Date1Name);
endif;
if (is_array($Date2Name)) :
$pieces2 = $Date2Name;
// Process second Date/Time field using custom function
if ($col == $pieces2[0]) $val = dateProcess($Date2Name);
endif;
// Build the UPDATE query
$val = isNull($val, $DBName);
$fields .= "`$col` = $val";
endif;
endforeach;
$sqlUpdate = "UPDATE $TableName SET $fields $Where";
// Custom function to process the INSERT query
DBConnect($sqlUpdate, "Update", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo."?ID=".intval($ID)));
endif;
// Delete record
elseif (isset($_POST["delete"])) :
// Build the DELETE query
$sqlDelete = "DELETE FROM $TableName WHERE ID=".intval($ID);
// Custom function to process the DELETE query
DBConnect($sqlDelete, "Delete", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo));
endif;
elseif (isset($_POST["clear"])) : // NOT CURRENTLY FUNCTIONAL
foreach ($_POST as $key=>$value) :
if ($key == 'clear') continue;
if (trim($key)) :
$key = "";
$value = "";
endif;
if (isset($_POST[$key])) :
unset($key);
endif;
endforeach;
endif;
}
我的一个站点有动态表单,这些表单被设置为来自几个MySQL表的值,而不是直接从表结构中获取,而这个站点有半动态表单。也就是说,表单是手动创建的,然后提交给函数进行处理,它已经很好地处理了,因此不涉及MySQL连接问题。但有一些领域没有处理,这就是我遇到的麻烦,你可能已经提供了一些线索,我需要解决它,谢谢!我以前没做过这种事,所以谢谢你的建议。好的,所以,你需要做的就是有一个方法手册,或者你需要做什么来创建过滤数组,这样你就可以得到一个列列表,允许按照我的答案中第一点的格式进行设置。我只有几分钟的时间来玩这个,但我把上面发布的filterArray和getUpdateStatement插入到我的函数中,看看它们会做什么。到目前为止,它看起来很有希望,尽管它给出了所有不使用的字段,并且没有任何值。我将离开一周,但明天在我离开之前,我将试着分析一下,看看需要什么。对不起,我不确定我是否明白你在说什么。你试过一些功能吗?是的,对不起,我按了回车键,它在我还在写的时候提交了。现在应该更正。您的插入和更新查询字符串不安全/容易受到注入攻击,因为您直接将用户提供的数据写入查询。为了解决这个问题,我建议使用带有占位符的mysqli或pdo语句。
function formProcess($ID,$DBName,$TableName,$PassName,$Date1Name,$Date2Name,$RemoveFields,$insertGoTo) {
// Insert record
if (isset($_POST["insert"])) :
unset($_POST["insert"]);
// Remove unneeded fields from $RemoveFields variable
if (!is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
// Build the INSERT query
foreach($filteredarray as $col => $val) :
// Process Password field
if ($PassName) :
// Encode password field
if ($col == $PassName && $val != "") $val=md5($val);
// If no changes, save original password
if ($col == $PassName && $val == "") continue;
endif;
// Process Date/Time fields using custom dateProcess()
if (is_array($Date1Name)) :
$pieces1 = $Date1Name;
if ($col == $pieces1[0]) $val = dateProcess($Date1Name);
endif;
if (is_array($Date2Name)) :
$pieces2 = $Date2Name;
if ($col == $pieces2[0]) $val = dateProcess($Date2Name);
endif;
$Fields[] = "`$col`";
$Values[] = isNull($val, $DBName);
endforeach;
$sqlInsert = "INSERT INTO $TableName (".implode(",",$Fields).")
VALUES (".implode(",",$Values).")";
// Custom function to process the INSERT query
$InsertID = DBConnect($sqlInsert, "Insert", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo."?ID=".intval($InsertID)));
endif;
// Update record
elseif (isset($_POST["update"])) :
unset($_POST['update']);
// Remove unneeded fields using array $RemoveFields variable
if (!is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
// Build the UPDATE query
$count = 0;
$fields = '';
$Where = '';
foreach($filteredarray as $col => $val) :
if ($count++ != 0 && $col != "ID") $fields .= ', ';
if ($col == "ID") :
$Where = " WHERE `$col` = " . intval($val);
else :
// Process Password field
if ($PassName) :
// Encode password field
if ($col == $PassName && $val != "") $val=md5($val);
// If no changes, save original password
if ($col == $PassName && $val == "") continue;
endif;
// Process Date/Time fields
if (is_array($Date1Name)) :
$pieces1 = $Date1Name;
// Process first Date/Time field using custom function
if ($col == $pieces1[0]) $val = dateProcess($Date1Name);
endif;
if (is_array($Date2Name)) :
$pieces2 = $Date2Name;
// Process second Date/Time field using custom function
if ($col == $pieces2[0]) $val = dateProcess($Date2Name);
endif;
// Build the UPDATE query
$val = isNull($val, $DBName);
$fields .= "`$col` = $val";
endif;
endforeach;
$sqlUpdate = "UPDATE $TableName SET $fields $Where";
// Custom function to process the INSERT query
DBConnect($sqlUpdate, "Update", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo."?ID=".intval($ID)));
endif;
// Delete record
elseif (isset($_POST["delete"])) :
// Build the DELETE query
$sqlDelete = "DELETE FROM $TableName WHERE ID=".intval($ID);
// Custom function to process the DELETE query
DBConnect($sqlDelete, "Delete", $DBName);
if ($insertGoTo) :
Redirect(sprintf('%s', $insertGoTo));
endif;
elseif (isset($_POST["clear"])) : // NOT CURRENTLY FUNCTIONAL
foreach ($_POST as $key=>$value) :
if ($key == 'clear') continue;
if (trim($key)) :
$key = "";
$value = "";
endif;
if (isset($_POST[$key])) :
unset($key);
endif;
endforeach;
endif;
}