Php 在嵌套循环中从Post中剥离值

Php 在嵌套循环中从Post中剥离值,php,forms,loops,foreach,Php,Forms,Loops,Foreach,我有一个用于动态构建更新查询的函数,该函数使用手动创建的表单,表单中的字段与表列的名称匹配,然后基于提交的字段名称和值构建查询。然而,我遇到了一个实例,其中某些已发布的字段必须过滤掉。如果手动操作,我可以很容易地完成这项工作,但我正试图在需要删除的列数(作为数组输入)不一定事先知道的情况下使其工作 例如,如果我用它来代替下面的一个foreach循环,它会起作用: $FieldName = array_values($Date1Name); // Remove $Date1Name submit

我有一个用于动态构建更新查询的函数,该函数使用手动创建的表单,表单中的字段与表列的名称匹配,然后基于提交的字段名称和值构建查询。然而,我遇到了一个实例,其中某些已发布的字段必须过滤掉。如果手动操作,我可以很容易地完成这项工作,但我正试图在需要删除的列数(作为数组输入)不一定事先知道的情况下使其工作

例如,如果我用它来代替下面的一个foreach循环,它会起作用:

$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;
}