php - mySQL-PHP : how to prepare queries with variables number of variables

标签 php mysql pdo

我已经通过 Stack Overflow 寻找答案,但问题仍然没有得到解答。这是我的问题:

  1. 我想通过 PHP 将表单中的 48 个 $_POST['textarea'] 值保存到 mySQL 数据库中。

  2. 因此数组执行方法由于参数过多而难以处理,

我在这篇文章( PHP Mysql PDO number of bound variables does not match number of tokens )中找到了帮助,它允许我“准备”、“绑定(bind)参数”和“执行”:当时第一个代码已经很大了。但我选择不要太敏感并接受这种不优雅。

  • 我的痛苦开始了:从现在开始,我将拥有可变数量(意味着每个用户都有不同的数量)$_POST['things'],并且从那时起循环似乎可能配置每个变量名称(为其处理 htmlspectialchar()bindParam() ),我面临这个不方便的问题:我不知道如何生成这些不同的变量名称。
  • 因此我尝试了上面的代码,但我遇到了没有问题的情况。

    1. 如何组织代码以创建与我的 $nbr_of_domain 一样多的变量以保存在数据库中变量?

    2. 还有一个教学问题:我之前已经学会了通过 execute(aray['param'=>$param 绑定(bind)参数...bindParam() 函数做同样的事情吗?那么它是否只对一定数量的参数有用?

    PS:最后你会发现html <form>代码(可能粗略地删除了敏感信息,但主要结构在这里)

    public function saveInfos()
    {   //Save info from main board into  database table user_board_items.
        $domain_assig='';
        $UM = new UserManager;
        if(isset($_SESSION['user_pseudo'])){
            $user_id=$UM->getUserId($_SESSION['user_pseudo']);
        }
        $DB=$this->dbConnect();
        $nbr_of_domain=$this->getNumberOfDomains();
        //BUILD REQUEST
        for($i=1; $i<=$nbr_of_domain;$i++){
          if($i<$nbr_of_domain){
            $domain_assig .='DM'.$i.'_ST_G=:DM'.$i.'_ST_G,'
                            .'DM'.$i.'_MT_G=:DM'.$i.'_MT_G,'
                            .'DM'.$i.'_LT_G=:DM'.$i.'_LT_G,'
                            .'DM'.$i.'_ST_T=:DM'.$i.'_ST_T,'
                            .'DM'.$i.'_MT_T=:DM'.$i.'_MT_T,'
                            .'DM'.$i.'_LT_T=:DM'.$i.'_LT_T,';
          }else {
            $domain_assig .='DM'.$i.'_ST_G=:DM'.$i.'_ST_G,'
                            .'DM'.$i.'_MT_G=:DM'.$i.'_MT_G,'
                            .'DM'.$i.'_LT_G=:DM'.$i.'_LT_G,'
                            .'DM'.$i.'_ST_T=:DM'.$i.'_ST_T,'
                            .'DM'.$i.'_MT_T=:DM'.$i.'_MT_T,'
                            .'DM'.$i.'_LT_T=:DM'.$i.'_LT_T';
          }
        }
        $req = sprintf("UPDATE user_board_items SET %s WHERE user_id=:user_id",$domain_assig);
        //PREPARING REQUEST
        $saveRequest = $DB->prepare($req);
        //PROTECTING PARAMETERS BEFORE BOUNDING
        for($i=1; $i<=$nbr_of_domain;$i++){
            $saveRequest->bindParam(':DM'.$i.'_ST_G',htmlspecialchars($_POST['DM'.$i.'_ST_G']));
            $saveRequest->bindParam(':DM'.$i.'_MT_G',htmlspecialchars($_POST['DM'.$i.'_MT_G']));
            $saveRequest->bindParam(':DM'.$i.'_LT_G',htmlspecialchars($_POST['DM'.$i.'_LT_G']));
            $saveRequest->bindParam(':DM'.$i.'_ST_T',htmlspecialchars($_POST['DM'.$i.'_ST_T']));
            $saveRequest->bindParam(':DM'.$i.'_MT_T',htmlspecialchars($_POST['DM'.$i.'_MT_T']));
            $saveRequest->bindParam(':DM'.$i.'_LT_T',htmlspecialchars($_POST['DM'.$i.'_LT_T']));
        }
            $saveRequest->bindParam(':user_id',$user_id);
    
        $saveRequest->execute();
        $saveRequest->closeCursor();
    }
    

    对于最勇敢的人来说,这是我旧的工作但严格的代码版本,它不允许变量 number 的变化(如此程序化!:):

    public function saveInfos()
    {   //Save info from main borad into  database table user_board_items
        //ini_set('memory_limit', '1024M'); // or you could use 1G
        $UM = new UserManager;
        if(isset($_SESSION['user_pseudo'])){
            $user_id=$UM->getUserId($_SESSION['user_pseudo']);
        }
        $DB=$this->dbConnect();
    
        $req = "UPDATE
                user_board_items
                SET
                DM1_ST_G=:DM1_ST_G,
                DM1_MT_G=:DM1_MT_G,
                DM1_LT_G=:DM1_LT_G,
                DM1_ST_T=:DM1_ST_T,
                DM1_MT_T=:DM1_MT_T,
                DM1_LT_T=:DM1_LT_T,
                DM2_ST_G=:DM2_ST_G,
                DM2_MT_G=:DM2_MT_G,
                DM2_LT_G=:DM2_LT_G,
                DM2_ST_T=:DM2_ST_T,
                DM2_MT_T=:DM2_MT_T,
                DM2_LT_T=:DM2_LT_T,
                DM3_ST_G=:DM3_ST_G,
                DM3_MT_G=:DM3_MT_G,
                DM3_LT_G=:DM3_LT_G,
                DM3_ST_T=:DM3_ST_T,
                DM3_MT_T=:DM3_MT_T,
                DM3_LT_T=:DM3_LT_T,
                DM4_ST_G=:DM4_ST_G,
                DM4_MT_G=:DM4_MT_G,
                DM4_LT_G=:DM4_LT_G,
                DM4_ST_T=:DM4_ST_T,
                DM4_MT_T=:DM4_MT_T,
                DM4_LT_T=:DM4_LT_T,
                DM5_ST_G=:DM5_ST_G,
                DM5_MT_G=:DM5_MT_G,
                DM5_LT_G=:DM5_LT_G,
                DM5_ST_T=:DM5_ST_T,
                DM5_MT_T=:DM5_MT_T,
                DM5_LT_T=:DM5_LT_T,
                DM6_ST_G=:DM6_ST_G,
                DM6_MT_G=:DM6_MT_G,
                DM6_LT_G=:DM6_LT_G,
                DM6_ST_T=:DM6_ST_T,
                DM6_MT_T=:DM6_MT_T,
                DM6_LT_T=:DM6_LT_T,
                DM7_ST_G=:DM7_ST_G,
                DM7_MT_G=:DM7_MT_G,
                DM7_LT_G=:DM7_LT_G,
                DM7_ST_T=:DM7_ST_T,
                DM7_MT_T=:DM7_MT_T,
                DM7_LT_T=:DM7_LT_T,
                DM8_ST_G=:DM8_ST_G,
                DM8_MT_G=:DM8_MT_G,
                DM8_LT_G=:DM8_LT_G,
                DM8_ST_T=:DM8_ST_T,
                DM8_MT_T=:DM8_MT_T,
                DM8_LT_T=:DM8_LT_T
                WHERE user_id=:user_id";
    
        $saveRequest = $DB->prepare($req);
    
        $DM1_ST_G= htmlspecialchars($_POST['DM1_ST_G']);
        $DM1_MT_G= htmlspecialchars($_POST['DM1_MT_G']);
        $DM1_LT_G= htmlspecialchars($_POST['DM1_LT_G']);
        $DM1_ST_T= htmlspecialchars($_POST['DM1_ST_T']);
        $DM1_MT_T= htmlspecialchars($_POST['DM1_MT_T']);
        $DM1_LT_T= htmlspecialchars($_POST['DM1_LT_T']);
        $DM2_ST_G= htmlspecialchars($_POST['DM2_ST_G']);
        $DM2_MT_G= htmlspecialchars($_POST['DM2_MT_G']);
        $DM2_LT_G= htmlspecialchars($_POST['DM2_LT_G']);
        $DM2_ST_T= htmlspecialchars($_POST['DM2_ST_T']);
        $DM2_MT_T= htmlspecialchars($_POST['DM2_MT_T']);
        $DM2_LT_T= htmlspecialchars($_POST['DM2_LT_T']);
        $DM3_ST_G= htmlspecialchars($_POST['DM3_ST_G']);
        $DM3_MT_G= htmlspecialchars($_POST['DM3_MT_G']);
        $DM3_LT_G= htmlspecialchars($_POST['DM3_LT_G']);
        $DM3_ST_T= htmlspecialchars($_POST['DM3_ST_T']);
        $DM3_MT_T= htmlspecialchars($_POST['DM3_MT_T']);
        $DM3_LT_T= htmlspecialchars($_POST['DM3_LT_T']);
        $DM4_ST_G= htmlspecialchars($_POST['DM4_ST_G']);
        $DM4_MT_G= htmlspecialchars($_POST['DM4_MT_G']);
        $DM4_LT_G= htmlspecialchars($_POST['DM4_LT_G']);
        $DM4_ST_T= htmlspecialchars($_POST['DM4_ST_T']);
        $DM4_MT_T= htmlspecialchars($_POST['DM4_MT_T']);
        $DM4_LT_T= htmlspecialchars($_POST['DM4_LT_T']);
        $DM5_ST_G= htmlspecialchars($_POST['DM5_ST_G']);
        $DM5_MT_G= htmlspecialchars($_POST['DM5_MT_G']);
        $DM5_LT_G= htmlspecialchars($_POST['DM5_LT_G']);
        $DM5_ST_T= htmlspecialchars($_POST['DM5_ST_T']);
        $DM5_MT_T= htmlspecialchars($_POST['DM5_MT_T']);
        $DM5_LT_T= htmlspecialchars($_POST['DM5_LT_T']);
        $DM6_ST_G= htmlspecialchars($_POST['DM6_ST_G']);
        $DM6_MT_G= htmlspecialchars($_POST['DM6_MT_G']);
        $DM6_LT_G= htmlspecialchars($_POST['DM6_LT_G']);
        $DM6_ST_T= htmlspecialchars($_POST['DM6_ST_T']);
        $DM6_MT_T= htmlspecialchars($_POST['DM6_MT_T']);
        $DM6_LT_T= htmlspecialchars($_POST['DM6_LT_T']);
        $DM7_ST_G= htmlspecialchars($_POST['DM7_ST_G']);
        $DM7_MT_G= htmlspecialchars($_POST['DM7_MT_G']);
        $DM7_LT_G= htmlspecialchars($_POST['DM7_LT_G']);
        $DM7_ST_T= htmlspecialchars($_POST['DM7_ST_T']);
        $DM7_MT_T= htmlspecialchars($_POST['DM7_MT_T']);
        $DM7_LT_T= htmlspecialchars($_POST['DM7_LT_T']);
        $DM8_ST_G= htmlspecialchars($_POST['DM8_ST_G']);
        $DM8_MT_G= htmlspecialchars($_POST['DM8_MT_G']);
        $DM8_LT_G= htmlspecialchars($_POST['DM8_LT_G']);
        $DM8_ST_T= htmlspecialchars($_POST['DM8_ST_T']);
        $DM8_MT_T= htmlspecialchars($_POST['DM8_MT_T']);
        $DM8_LT_T= htmlspecialchars($_POST['DM8_LT_T']);
    
        $saveRequest->bindParam(':DM1_ST_G',$DM1_ST_G);
        $saveRequest->bindParam(':DM1_MT_G',$DM1_MT_G);
        $saveRequest->bindParam(':DM1_LT_G',$DM1_LT_G);
        $saveRequest->bindParam(':DM1_ST_T',$DM1_ST_T);
        $saveRequest->bindParam(':DM1_MT_T',$DM1_MT_T);
        $saveRequest->bindParam(':DM1_LT_T',$DM1_LT_T);
        $saveRequest->bindParam(':DM2_ST_G',$DM2_ST_G);
        $saveRequest->bindParam(':DM2_MT_G',$DM2_MT_G);
        $saveRequest->bindParam(':DM2_LT_G',$DM2_LT_G);
        $saveRequest->bindParam(':DM2_ST_T',$DM2_ST_T);
        $saveRequest->bindParam(':DM2_MT_T',$DM2_MT_T);
        $saveRequest->bindParam(':DM2_LT_T',$DM2_LT_T);
        $saveRequest->bindParam(':DM3_ST_G',$DM3_ST_G);
        $saveRequest->bindParam(':DM3_MT_G',$DM3_MT_G);
        $saveRequest->bindParam(':DM3_LT_G',$DM3_LT_G);
        $saveRequest->bindParam(':DM3_ST_T',$DM3_ST_T);
        $saveRequest->bindParam(':DM3_MT_T',$DM3_MT_T);
        $saveRequest->bindParam(':DM3_LT_T',$DM3_LT_T);
        $saveRequest->bindParam(':DM4_ST_G',$DM4_ST_G);
        $saveRequest->bindParam(':DM4_MT_G',$DM4_MT_G);
        $saveRequest->bindParam(':DM4_LT_G',$DM4_LT_G);
        $saveRequest->bindParam(':DM4_ST_T',$DM4_ST_T);
        $saveRequest->bindParam(':DM4_MT_T',$DM4_MT_T);
        $saveRequest->bindParam(':DM4_LT_T',$DM4_LT_T);
        $saveRequest->bindParam(':DM5_ST_G',$DM5_ST_G);
        $saveRequest->bindParam(':DM5_MT_G',$DM5_MT_G);
        $saveRequest->bindParam(':DM5_LT_G',$DM5_LT_G);
        $saveRequest->bindParam(':DM5_ST_T',$DM5_ST_T);
        $saveRequest->bindParam(':DM5_MT_T',$DM5_MT_T);
        $saveRequest->bindParam(':DM5_LT_T',$DM5_LT_T);
        $saveRequest->bindParam(':DM6_ST_G',$DM6_ST_G);
        $saveRequest->bindParam(':DM6_MT_G',$DM6_MT_G);
        $saveRequest->bindParam(':DM6_LT_G',$DM6_LT_G);
        $saveRequest->bindParam(':DM6_ST_T',$DM6_ST_T);
        $saveRequest->bindParam(':DM6_MT_T',$DM6_MT_T);
        $saveRequest->bindParam(':DM6_LT_T',$DM6_LT_T);
        $saveRequest->bindParam(':DM7_ST_G',$DM7_ST_G);
        $saveRequest->bindParam(':DM7_MT_G',$DM7_MT_G);
        $saveRequest->bindParam(':DM7_LT_G',$DM7_LT_G);
        $saveRequest->bindParam(':DM7_ST_T',$DM7_ST_T);
        $saveRequest->bindParam(':DM7_MT_T',$DM7_MT_T);
        $saveRequest->bindParam(':DM7_LT_T',$DM7_LT_T);
        $saveRequest->bindParam(':DM8_ST_G',$DM8_ST_G);
        $saveRequest->bindParam(':DM8_MT_G',$DM8_MT_G);
        $saveRequest->bindParam(':DM8_LT_G',$DM8_LT_G);
        $saveRequest->bindParam(':DM8_ST_T',$DM8_ST_T);
        $saveRequest->bindParam(':DM8_MT_T',$DM8_MT_T);
        $saveRequest->bindParam(':DM8_LT_T',$DM8_LT_T);
        $saveRequest->bindParam(':user_id',$user_id);
    
        $saveRequest->execute();
        $saveRequest->closeCursor();
    }
    

    还有 html:

    <form id="theForm" enctype="multipart/form-data" action="index.php?action=saveBoardInfo" method="post">
    <table>
    <thead>
      <th class="head_row"> TITLES</th>
      <th class="head_row" >SINGULAR SAMPLE PROCESS</th>
      <th class="head_row" >FILE</th>
      <th class="head_row" >MEDIUM SAMPLE PROCESS</th>
      <th class="head_row" >FILE</th>
      <th class="head_row" >LARGE SAMPLE PROCESS</th>
      <th class="head_row" >FILE</th>
    </thead>
    <tbody>
      <?php
          foreach ($names as $number=>$domain) {
           ?>
              <!-- FIRST HALF ROW -->
              <tr <?=$number+1?>">
                <!-- 2 merged rows-->
                <td not_editable" rowspan="2">
                  <span class="color_category" style="background-color:<?=$color[$number]?>;"></span>
                  <span ><?=$number + 1 ?></span>
                </td>
                <!-- Description cell ST-->
                <td class="inputContainerTdCell">
                    <textarea id="<?='DM'.($number+1) .'_'.'ST_G'?>" name="<?='DM'.($number+1) .'_'.'ST_G'?>" class="userInput" value="" placeholder="SINGULAR TEST SAMPLE GENERAL DESCRIPTION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'ST_G'])?></textarea>
                </td>
                <!-- Description cell MT-->
                <td class="inputContainerTdCell">
                    <textarea id="<?='DM'.($number+1) .'_'.'LT_G'?>" name="<?='DM'.($number+1) .'_'.'MT_G'?>" class="userInput" value="" placeholder="MEDIUM TEST SAMPLE GENERAL DESCRIPTION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'LT_G'])?></textarea>
                </td>
                <!-- Description cell LT-->
                <td class="inputContainerTdCell">
                    <textarea id="<?='DM'.($number+1) .'_'.'LT_G'?>" name="<?='DM'.($number+1) .'_'.'LT_G'?>" class="userInput" value="" placeholder="LARGE TEST SAMPLE DESCRIPTION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'LT_G'])?></textarea>
                </td>
    
                <!-- File import part not mentionned here: 2 merged rows-->
    
              <!-- SECOND HALF ROW -->
              <tr>
                <td class="inputContainerTdCell userInput">
                  <textarea id="<?='DM'.($number+1) .'_'.'ST_T'?>" name="<?='DM'.($number+1) .'_'.'ST_T'?>" value="" placeholder="SINGULAR TEST IN PREPARATION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'ST_T'])?></textarea>
                </td>
                <td class="inputContainerTdCell userInput">
                  <textarea id="<?='DM'.($number+1) .'_'.'MT_T'?>" name="<?='DM'.($number+1) .'_'.'MT_T'?>" value="" placeholder="MEDIUM TEST IN PREPARATION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'MT_T'])?></textarea>
                </td>
                <td class="inputContainerTdCell userInput">
                  <textarea id="<?='DM'.($number+1) .'_'.'LT_T'?>" name="<?='DM'.($number+1) .'_'.'LT_T'?>" value="" placeholder="LARGE TEST IN PREPARATION"><?= htmlspecialchars($board_items['DM'.($number+1) .'_'.'LT_T'])?></textarea>
                </td>
              </tr>
    
              <!-- SEPARATORS: INVISIBLE SEPARATION ROW -->
              <tr style="height:2px;"></tr>
              <?php
              } 
              ?>
    </tbody>
    </table>
    </form>
    

    最佳答案

    您的代码表明数据库结构非常差。拥有大量这样的列说明非常not normal数据库。也就是说,您正在尽最大努力利用您拥有的数据库;不过,有几点可以显着压缩代码。

    在实际以 HTML 形式显示数据之前,您不会转义 HTML 显示的数据。切勿将其存储在转义的数据库中,否则当有人想要 PDF 中的数据或输出到命令行时,您会不高兴。

    PDO不需要绑定(bind)参数;仅在不明确的情况下才需要这样做,例如未正确推断数据类型,或者需要从存储过程取回数据。只需将参数数组传递给执行函数即可。

    我还压缩了用于构建查询的代码,并且参数数组是在同一循环内从 $_POST 构建的。

    <?php
    public function saveInfos()
    {
        $UM = new UserManager;
        if(isset($_SESSION['user_pseudo'])){
            $user_id = $UM->getUserId($_SESSION['user_pseudo']);
        }
        $DB = $this->dbConnect();
        $nbr_of_domain = $this->getNumberOfDomains();
        $fields = ["ST_G", "MT_G", "LT_G", "ST_T", "MT_T", "LT_T"];
        //BUILD QUERY AND PARAMETERS
        $params[':user_id'] = $user_id;
        for($i = 1; $i <= $nbr_of_domain; $i++) {
            foreach ($fields as $field) {
                $domain_assig[] = "DM{$i}_{$field} = :DM{$i}_{$field}";
                $params[":DM{$i}_{$field}"] = $_POST["DM{$i}_{$field}"];
                // if passing parameters to execute() truly is a problem,
                // you could delete the line above and then run this same
                // loop again to bind parameters, as in the comment below
            }
        }
        $req = sprintf(
            "UPDATE user_board_items SET %s WHERE user_id=:user_id",
            implode(",", $domain_assig)
        );
        //PREPARING REQUEST
        $saveRequest = $DB->prepare($req);
        // if passing parameters to execute() truly is a problem...
        /*
        $saveRequest->bindParam(":user_id", $user_id);
        for($i = 1; $i <= $nbr_of_domain; $i++) {
            foreach ($fields as $field) {
                $saveRequest->bindParam(":DM{$i}_{$field}", $_POST["DM{$i}_{$field}"]);
            }
        }
        */
        $saveRequest->execute($params);
        $saveRequest->closeCursor();
    }
    

    关于数据库规范化,您的数据库结构当前如下所示:

    +----+---------+----------+----------+----------+     +----------+
    | id | user_id | DM1_ST_G | DM1_MT_G | DM1_LT_G | ... | DM8_LT_T |
    +----+---------+----------+----------+----------+     +----------+
    | 17 | 12345   | aaa      | aaa      | aaa      | ... | hhh      |
    +----+---------+----------+----------+----------+     +----------+
    

    它应该看起来像这样:

    +----+---------+----+------+------+------+------+------+------+
    | id | user_id | DM | ST_G | MT_G | LT_G | ST_T | MT_T | LT_T |
    +----+---------+----+------+------+------+------+------+------+
    | 11 | 12345   | 1  | aaa  | aaa  | aaa  | aaa  | aaa  | aaa  |
    | 12 | 12345   | 2  | bbb  | bbb  | bbb  | bbb  | bbb  | bbb  |
    ...
    | 18 | 12345   | 8  | hhh  | hhh  | hhh  | hhh  | hhh  | hhh  |
    +----+---------+----+------+------+------+------+------+------+
    

    然后您可以根据用户 ID 选择任意行数。想象一下这样一种情况,您有几十万行,并且您决定添加另一组 DM9_* 列。现在这样,整个表都要重建,你的代码也要调整,很乱。

    关于php - mySQL-PHP : how to prepare queries with variables number of variables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58982206/

    相关文章:

    php - sql过程导入错误

    mysql - SQL 中的子查询

    Zend 中的 PHP 数据对象

    php - Symfony Doctrine QueryBuilder 在 Join 上添加 where 子句

    php - 每 24 小时运行一次 php 任务

    php - 我应该如何将数组值存储在 MySQL 数据库中?

    mysql - 获取一行中的预览下一条记录

    php - 如何使用类似于pdo的mysqli一次插入多条记录

    php - MySQL Where 子句值 0 和 1 无法正常工作

    php - 如何以这种方式格式化 mysql 表?