Php mysqli(multi)\u查询-如何在循环中执行?

Php mysqli(multi)\u查询-如何在循环中执行?,php,mysql,mysqli,Php,Mysql,Mysqli,在为我的新网站创建了一些函数之后,我很快意识到所有使用永久编程的include文件都无法控制,因此我决定学习并将我当前编写的函数转换为OOP类,并从mysql转换为mysqli。到目前为止,转换还不算太糟糕,但我已经实现了一个具有/需要多个查询的函数,其中一个查询是在更新数据之前检查数据的选择。到目前为止,我用事先准备好的语句写的东西很有魅力,但它只做选择。我陷入困境的地方是更新数据库的时候到了。以下是我目前掌握的情况: public function ban() { $connection

在为我的新网站创建了一些函数之后,我很快意识到所有使用永久编程的include文件都无法控制,因此我决定学习并将我当前编写的函数转换为OOP类,并从mysql转换为mysqli。到目前为止,转换还不算太糟糕,但我已经实现了一个具有/需要多个查询的函数,其中一个查询是在更新数据之前检查数据的选择。到目前为止,我用事先准备好的语句写的东西很有魅力,但它只做选择。我陷入困境的地方是更新数据库的时候到了。以下是我目前掌握的情况:

public function ban() {
  $connection  = Database::getConnection();
  $user_id = $_POST['user'];
  $feedback = '';
  $query = "SELECT banned, user_name
            FROM users
            WHERE user_id = ?";
  $stmt = $connection -> prepare($query);

  // Check for a multi-user selection on POST
  if (count($user_id) > 1) {
     foreach ($user_id as $value) {
        $stmt -> bind_param('i', $value);
        if (!$result = $stmt -> execute()) {
           $feedback .= "Did not execute.";
        } else {
           $stmt -> bind_result($banned, $user);
           $stmt -> fetch();
           if ($banned == 1) {
              $feedback .= $user . " is already banned.<br />";
           } else {
              // This is where I need the code to update the database
              // with the users who aren't already banned.
           }
        }
     }
     $stmt -> close();
     return $feedback;
  } else {
     // This is where the UPDATE will be for a single person ban
     // if only one was selected on POST
  } 
}

在此方面的任何帮助都将不胜感激。希望我能解释清楚我需要做什么。如果没有,请告诉我。谢谢

代码示例仍然是非常程序化的

您应该有一个方法来检查用户是否被禁止,以及一个方法来禁止用户

user\u banked方法应采用user\u id并返回布尔值

ban_用户方法应包含原因和用户id

应该有另一个函数或方法执行循环

将用户id转换为数组,您可以执行一个循环

使用异常处理错误

<?php
    //the model
    ...  

    public function update_users (array $user_ids)
    {
       $result = array();         

       foreach ($user_ids as $user_id) {
           if (!$this->user_banned($user_id)) {
               $this->ban_user($user_id, $reason);

           } else {
               $result[$user_id] = "already banned";
           }

        return $result;
    }
    ...

    //the controller

    //prevent XSS, cast as integers or use filter_var or something
    $user_ids = sanitize((array) $_POST['user']);
    try {
        $result = $obj->update_users($user_ids);
    } catch (Exception $e) {
    ...

当我重新阅读我的问题时,我开始考虑使用第二条准备好的语句进行更新。首先,我试图在初始的
foreach
循环中包含第二条语句,但出现了错误,可能是因为一次打开的语句不能超过一条。接下来我决定将每次迭代的值(正在检查的用户id)存储到一个单独的数组中,然后,在关闭初始
foreach
循环和prepared语句后,我使用新的prepared语句为
UPDATE
运行第二个循环,瞧!下面是代码的外观:

public function ban() {
  $connection  = Database::getConnection();
  $user_id = $_POST['user'];
  $reason = $_POST['banExplain'];
  $update = array();
  $feedback = '';
  $query = "SELECT banned, user_name
            FROM users
            WHERE user_id = ?";
  $query2 = "UPDATE users
             SET banned = '1', ban_reason = ?
             WHERE user_id = ?";
  $stmt = $connection -> prepare($query);
  $stmt2 = $connection -> prepare($query2);

  if (count($user_id) > 1) {
     foreach ($user_id as $value) {
        $stmt -> bind_param('i', $value);            
        if (!$result = $stmt -> execute()) {
           $feedback .= "Did not execute search.<br />";
        } else {
           $stmt -> bind_result($banned, $user);
           $stmt -> fetch();
           if ($banned == 1) {
              $feedback .= $user . " is already banned.<br />";
           } else {
              $update["$user"] = $value; // Populate an array to pass to update loop
           }
        }
     }
     $stmt -> close();

     // Run update query - $key from $update var is the user name
     foreach ($update as $key => $value) {
        $stmt2 -> bind_param('si', $reason, $value);
        if (!$result2 = $stmt2 -> execute()){
           $feedback .="Did not execute update.<br />";
        } else {
           $feedback .= $key . " is banned.<br />";
        }
     }
     $stmt2 -> close();
     return $feedback;
  } else {

     // Executes for single selection requests
     $stmt -> bind_param('i', $user_id);
     if (!$result = $stmt -> execute()) {
        $feedback .= "Did not execute search.<br />";
     } else {
        $stmt -> bind_result($banned, $user);
        $stmt -> fetch();
        if ($banned == 1) {
           $feedback .= $user . " is already banned.<br />";
        } else {
           $update["$user"] = $user_id;
        }
     }
     $stmt -> close();
     // Runs loop simply for the user name in the $key var
     foreach ($update as $key => $value) {
        $stmt2 -> bind_param('si', $reason, $value);
        if (!$result2 = $stmt2 -> execute()){
           $feedback .="Did not execute update.<br />";
        } else {
           $feedback .= $key . " is banned.<br />";
        }
     }
     $stmt2 -> close();
     return $feedback;
  }
检查DB ban值的方法:

private function check\u ban($user\u id,$arg){
$connection=Database::getConnection();
$query=“选择禁止,用户名”
来自用户
其中用户_id=?”;
$stmt=$connection->prepare($query);
foreach($user\u id作为$value){
$stmt->bind_参数('i',$value);
如果(!$result=$stmt->execute()){
返回FALSE;
}否则{
$stmt->bind_result($banked,$user);
$stmt->fetch();
如果($arg==1&&$banked==1){
$this->feedback.=$user.“已被禁止。
”; }elseif($arg==0&&$banked==0){ $this->feedback.=$user.。当前未被禁止。
; }否则{ $this->update[“$user”]=$value;//填充要取消/禁止的数组 } } } $stmt->close(); 返回TRUE; }
最后是使用un/ban更新数据库的方法:

private function ban_user($arg) {
  $connection = Database::getConnection();
  $update = $this -> update;
  $reason = $this -> banReason;
  $query = "UPDATE users
            SET banned = ?, ban_reason = ?
            WHERE user_id = ?";
  $stmt = $connection -> prepare($query);

  foreach ($update as $key => $value) {
     $stmt -> bind_param('isi', $arg, $reason, $value);
     if (!$result = $stmt -> execute()) {
        return FALSE;
     } elseif ($arg == 0) {
        $this -> feedback .= $key . " is unbanned.<br />";
     } else {
        $this -> feedback .= $key . " is banned.<br />";
     }
  }
  $stmt -> close();
  return TRUE;
}
私有函数禁止用户($arg){
$connection=Database::getConnection();
$update=$this->update;
$reason=$this->banReason;
$query=“更新用户”
设置禁止=?,禁止原因=?
其中用户_id=?”;
$stmt=$connection->prepare($query);
foreach($key=>$value更新){
$stmt->bind_参数('isi',$arg,$reason,$value);
如果(!$result=$stmt->execute()){
返回FALSE;
}elseif($arg==0){
$this->feedback.=$key.“已取消绑定。
”; }否则{ $this->feedback.=$key.“被禁止。
”; } } $stmt->close(); 返回TRUE; }
注意,在这些方法中很少发生错误检查/过滤/消毒。我有两个原因:变量的值在脚本中被选中,我是唯一被授予这样做的权限的人,像
$user\u id
这样的变量的值被预先填充到复选框和下拉列表中,其中包含数据库中的精确值,因此发生错误的
$user\u id
的可能性微乎其微

正如我在其他帖子中提到的,如果有人能为我所做的事情提供更好的解决方案,请让我知道


感谢这么好的社区

对,代码仍然是非常程序化的。在发布了这个问题之后,我提出了一个解决方案,虽然不是一个更OOP的风格,只是一个更长的版本(见我的回答)。但是它是有效的。不过,我现在会接受你的建议,看看是否可以将其分解为更小、更OOP风格的函数。
public function ban($arg) {              // 0 = Unban 1 = Ban
  $this -> user_id = $_POST['user'];     // initially set user id as global variable
  $user_id = $this -> user_id;
  $this -> banReason = mysqli_real_escape_string($_POST['banExplain']);

  if (!$this -> check_ban($user_id, $arg)) {
     $this -> feedback .= Admin::CONNFAIL;
     return $this -> feedback;           // Returned connection failure on select
  } elseif (!$this -> ban_user($arg)) {
     $this -> feedback .= Admin::UPFAIL;
     return $this -> feedback;           // Returned connection failure on update
  } else {
     return $this -> feedback;
  }
}
private function check_ban($user_id, $arg) {
  $connection = Database::getConnection();
  $query = "SELECT banned, user_name
            FROM users
            WHERE user_id = ?";
  $stmt = $connection -> prepare($query);

  foreach ($user_id as $value) {
     $stmt -> bind_param('i', $value);
     if (!$result = $stmt -> execute()) {
        return FALSE;
     } else {
        $stmt -> bind_result($banned, $user);
        $stmt -> fetch();
        if ($arg == 1 && $banned == 1) {
           $this -> feedback .= $user . " is already banned.<br />";
        } elseif ($arg == 0 && $banned == 0) {
           $this -> feedback .= $user . " is not currently banned.<br />";
        } else {
           $this -> update["$user"] = $value;  // Populate array to be un/banned
        }
     }
  }
  $stmt -> close();
  return TRUE;
}
private function ban_user($arg) {
  $connection = Database::getConnection();
  $update = $this -> update;
  $reason = $this -> banReason;
  $query = "UPDATE users
            SET banned = ?, ban_reason = ?
            WHERE user_id = ?";
  $stmt = $connection -> prepare($query);

  foreach ($update as $key => $value) {
     $stmt -> bind_param('isi', $arg, $reason, $value);
     if (!$result = $stmt -> execute()) {
        return FALSE;
     } elseif ($arg == 0) {
        $this -> feedback .= $key . " is unbanned.<br />";
     } else {
        $this -> feedback .= $key . " is banned.<br />";
     }
  }
  $stmt -> close();
  return TRUE;
}