Когда я перечитал свой вопрос, у меня возникла мысль об использовании второго подготовленного утверждения для обновления. Во-первых, я попытался включить второй оператор в начальный цикл foreach
, но он допустил ошибку, возможно потому, что вы не можете открыть более одного оператора за раз. Затем я решил сохранить значение (проверяемый user_id) на каждой итерации в отдельном массиве, а затем, закрыв начальный цикл foreach
и подготовленный оператор, я запустил второй цикл, используя новый подготовленный оператор для 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;
}
}
Довольно долго для того, что кажется такой простой задачей, и я думаю, что mysqli::multi_query
, вероятно, все еще лучший способ сделать это (после использования mysqli::real_escape
для добавления необходимой защиты), но кроме громоздкость этой функции, она работает и безопасна (насколько я могу судить), сохраняя при этом минимальную стоимость запроса к серверу.
Я собираюсь сейчас воспользоваться советом user934258 и попытаться разбить его на более мелкие, более простые для усвоения и поддержки функций класса. Если / когда я завершу это, я продолжу здесь, чтобы показать результаты, которые, мы надеемся, помогут другим в том же затруднительном положении. Если у кого-то есть хорошие решения, пожалуйста, дайте мне знать. Я всегда пытаюсь улучшить свое кодирование
Спасибо всем, надеюсь, это хотя бы поможет кому-то еще в такой же ситуации.
Хорошо, хорошо, благодаря user934258 Я вернулся и повторно проверил кодирование этого / этих методов. Следуя его советам, я смог вырезать около 25 строк кода из методов запрета. Но, имея всего пару дополнительных строк и передавая / вставляя дополнительный аргумент, я смог сделать код многоцелевым, чтобы включить метод unban, который, в свою очередь, удаляет около 77 строк ненужного повторяющегося кода (unban был зеркальной копией запрет, за исключением того, что он проверял Ноль вместо Единицы в БД и отображал немного другой ответ.) Для тех из вас, кто в будущем может найти эту тему полезной, вот конечный продукт моего кода.
Метод, вызываемый из скрипта:
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;
}
И, наконец, способ обновить БД с помощью 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;
}
Обратите внимание, что в этих методах происходит очень мало проверки / фильтрации / очистки от ошибок. У меня есть несколько причин для этого: значения переменных проверяются в сценарии, я единственный, кому предоставлены права на это, а значения для переменных, таких как $user_id
, предварительно заполнены в флажках и раскрывающихся списках с помощью точные значения из БД, так что вероятность ошибочного $user_id
невелика.
Как я уже упоминал в других постах, если кто-то может предложить лучшее решение для того, что я сделал, пожалуйста, дайте мне знать.
Спасибо за такое замечательное сообщество!