大型表单 = 大型 PHP/mySql 查询语句... 有好的解决方案吗?

4
我正在构建一个内容管理系统,其中有一个包含大量数据的表单需要添加到我的数据库中。这是我收集变量的地方...
$orgName = $_POST['orgName'];
$impact = $_POST['impact'];
$headline = $_POST['headline'];
$content = $_POST['content'];
$subContent = $_POST['subContent'];
$meterText = $_POST['meterText'];
$month = $_POST['month'];
$shopLink = $_POST['shopLink'];
$blurbTitle = $_POST['blurbTitle'];
$blurb = $_POST['blurb'];
$logoURL = $_POST['logoURL'];
$buttonURL = $_POST['buttonURL'];
$blurbURL = $_POST['blurbURL'];
$POMURL = $_POST['POMURL'];
$horizontalURL = $_POST['horizontalURL'];
$statURL = $_POST['statURL'];
$stats = $_POST['stats'];

我在这里使用 SQL 转义、验证并发送到我的函数(略去了空间的验证)...

require_once 'DB_Connect.php';

$connection = new DB_Connect();    

$connection->insertPartner(
    $index,
    mysql_real_escape_string($orgName),
    mysql_real_escape_string($impact),
    mysql_real_escape_string($headline),
    mysql_real_escape_string($content),
    mysql_real_escape_string($subContent),
    $month,
    mysql_real_escape_string($shopLink),
    mysql_real_escape_string($blurbTitle),
    mysql_real_escape_string($meterText),
    mysql_real_escape_string($blurb),
    mysql_real_escape_string($stats),
    mysql_real_escape_string($logoURL),
    mysql_real_escape_string($buttonURL),
    mysql_real_escape_string($blurbURL),
    mysql_real_escape_string($POMURL),
    mysql_real_escape_string($horizontalURL),
    mysql_real_escape_string($statURL)
    ))

最后,该函数...
public function insertPartner(
    $orgName = '',
    $impact = '',
    $headline = '',
    $content = '',
    $subContent = '',
    $month = '',
    $shopLink = '',
    $blurbTitle = '',
    $blurb = '',
    $stats = '',
    $logoURL = '',
    $buttonURL = '',
    $blurbURL = '',
    $POMURL = '',
    $horizontalURL = '',
    $statURL = '')
    {
        $query="INSERT INTO `hupcap_FCE`.`fce_partners` (
        `index`,
        `organization_name`,
        `impact`,
        `headline`,
        `content`,
        `sub_content`,
        `blurb_title`,
        `blurb`,
        `stats`,
        `month`,
        `meter_number`,
        `meter_text`,
        `shop_link`,
        `button_img_url`,
        `blurb_img_url`,
        `logo_url`,
        `month_img_url`,
        `horizontal_logo_url`,
        `stat_img_url`,
        `util`
        ) VALUES (
        '',
        '$orgName',
        '$impact',
        '$headline',
        '$content',
        '$subContent',
        '$blurbTitle',
        '$blurb',
        '$stats',
        '$month',
        0,
        '',
        '$shopLink',
        '$buttonURL',
        '$blurbURL',
        '$logoURL',
        '$POMURL',
        '$horizontalURL',
        '$statURL',
        0)";
        if(mysql_query($query)){
            return true;
        }else{
            die("failed to insert record" . mysql_error());
        }
    }

肯定有更加高效的方法来完成这个任务。 谁有最好的方法呢?

谢谢 -J


作为建议,一般而言,参数传递的最大值约为7或8个。而你有15个。 - Anthony Forloney
@Anthony Forloney 我不知道有关于参数传递的经验法则... 我想数组可能是一个更好的选择? - Howard Zoopaloopa
关于参数传递的经验法则并非生死攸关,而更多是人们适应的惯例。数组是一种替代方案。 - Anthony Forloney
5个回答

4

选项#1

使用像Doctrine这样的ORM来处理您的PHP应用程序中的CRUD操作。

选项#2

如果使用ORM是一个太大的范式转变,可以尝试类似以下方式:

// Alias $_POST fields to SQL columns
$sql_columns= array(
    'post_field1'=> 'sql_column1',
    'post_field2'=> 'sql_column2',
    'post_field3'=> 'sql_column3');

// Encode $_POST data for use in SQL
$sql_a= array();
foreach ($sql_columns as $k=> $k2) {
 if (isset($_POST[$k])) {
  $sql_a[]= sprintf("`%s` = '%s'", $k2, mysql_real_escape_string($_POST[$k]));
 }
}

// Build SQL string to execute
$sql= sprintf('INSERT INTO table_name SET %s', implode(', ', $sql_a));
var_dump($sql);

这可以很容易地扩展为一个函数或一个类,以处理不同的表、列和SQL语句。

现在我得查一下sprintf是什么鬼。我看了ORM Doctrine。我终于对编写PHP类感到舒适了。我可以去那里,但我认为我至少还需要六个月才能将ORM添加到我的工具箱中。而且,如果我没记错的话,它似乎是需要安装的?我从Hostgator租用服务器空间,我很幸运能够使用phpMyAdmin。(实际上,他们对我还不错)。谢谢你的回复。我相信一旦我理解了它,我会很高兴的;) - Howard Zoopaloopa

1
如果您的表中有16列,则插入语句将会很长。您应该使用数据库包装类之一(例如PDO)。首先,它为您提供了方便的方式来使用预处理语句(避免SQL注入并添加类型检查)。其次,它使添加参数更加可读,因为您不必连接一个巨大的字符串。
function insert_stuff($col1, $col2, $col3) {
    $conn = new PDO($connectionString);
    $query = "insert into my_table (col1, col2, col3) values (:col1, :col2, :col3)";
    $statement = $conn->prepare($query);

    $statement->bindValue(":col1", $col1);
    $statement->bindValue(":col2", $col2);
    $statement->bindValue(":col3", $col3);

    $statement->execute();
    // etc. 
}

如果你真的被所有的打字困扰,你可以使用数据库为你生成一些代码:

select 
    concat('$statement->bindValue(":', column_name, '", $', column_name, ');' 
from
    information_schema.columns
where
    table_schema = 'my_database_name'
and table_name = 'my_table_name';

1

使用foreach循环遍历params数组,以便您可以检查值。在最终函数内部进行一些魔法,以便您可以检查它们中是否有任何一个为空或其他情况...


嗯,我不太明白这个,他是想要移除空字段吗? - Sarfraz
他正在寻找更好的方法来完成这个,或者可能缩短代码并提高速度 :) 谢谢 - Sarfraz

0

类似这样的代码可以工作:

$insertArray() = array();
foreach ($_POST as $key=> $name)
{
    $insertArray[$name] = mysql_real_escape_string($_POST[$name]);
}
$query = "INSERT INTO `hupcap_FCE`.`fce_partners` (" . implode(',', array_keys($insertArray)) VALUES '" . implode("','", $insertArray) . "'";
//...

这不是安全的,但它可以工作 :)


-1

是的,对大部分来说似乎是正确的,但你可以通过以下方式在很大程度上保护自己:

不要写成:

$orgName = $_POST['orgName'];
$impact = $_POST['impact'];
$headline = $_POST['headline'];
$content = $_POST['content'];
$subContent = $_POST['subContent'];
$meterText = $_POST['meterText'];
$month = $_POST['month'];
$shopLink = $_POST['shopLink'];
$blurbTitle = $_POST['blurbTitle'];
$blurb = $_POST['blurb'];
$logoURL = $_POST['logoURL'];
$buttonURL = $_POST['buttonURL'];
$blurbURL = $_POST['blurbURL'];
$POMURL = $_POST['POMURL'];
$horizontalURL = $_POST['horizontalURL'];
$statURL = $_POST['statURL'];
$stats = $_POST['stats'];

你可以简单地写下这一行代码:
extract($_POST, EXTR_SKIP);

现在你可以使用之前所述的所有变量,例如,你可以使用它们或者输出它们:

echo $orgName;
echo $impact;
echo $headline;

需要添加的内容:我不确定在安全方面使用extract是否是一个好的做法,但是到目前为止我一直在使用它而没有遇到任何问题 :)


1
默认情况下,extract将覆盖现有变量。至少要像这样调用它:extract($a, EXTR_SKIP),以防止攻击者破坏您现有的代码。 - leepowers
@pygorex - 没错,想象一下如果有一个变量$isAdmin之类的东西,然后有人POST了一个值为"true"的"isAdmin"... 不管怎样,这并没有真正帮助到楼主,因为这些值仍然没有经过消毒处理。 - John Rasch
喜欢 extract 函数。将来很高兴能够使用它。 - Howard Zoopaloopa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接