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