从嵌套循环中的帖子中剥离值

时间:2017-07-21 01:13:41

标签: php forms loops foreach

我有一个用于动态构建更新查询的函数,该函数的工作方式是手动创建的表单,其中包含与表列名称匹配的字段,然后根据提交的字段名称和值构建查询。但是,我遇到了必须过滤掉某些已发布字段的实例。如果手动完成,我可以很容易地完成它,但是当我要提前知道要删除的列数时,我试图使其工作。

例如,如果我使用它代替下面的一个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;
}

2 个答案:

答案 0 :(得分:1)

我过去做过类似的任务,也许会给你一些想法。这假设您正在使用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;
    }

以上函数将在简单的user表上返回:

Array
(
    [0] => ID
    [1] => username
    [2] => password
    [3] => first_name
    [4] => last_name
    [5] => email
    [6] => country
    [7] => usergroup
    [8] => user_status
    [9] => timestamp
)

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']数组中。希望这是你正在寻找的东西,或者它可能会给你一些想法。

答案 1 :(得分:0)

立即工作并更新以处理插入,更新和删除操作。我决定由于需要一些特殊的字段处理,我无法为更新和插入查询构建单独的函数,所以我将功能移回主formProcess()函数。我确实需要过滤掉某些字段,而不是说要保留哪些字段,因此想出了一种方法,使用array_diff_key()和array_flip()的组合来实现这一点。这提供了要处理的所有字段的数组。这样做的主要原因是过滤掉日,月和年选择器,然后将它们处理成一个字段:

$ filteredarray = array_diff_key($ _ POST,array_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;
}