私の質問を読み返したので、私は更新のために2番目の準備文を使用することを考えました。最初に、最初のforeach
ループ内に2番目のステートメントを含めることを試みましたが、1度に1つ以上のステートメントを開くことができないため、おそらくエラーが発生しました。私が次に決定したのは、最初のforeach
ループとプリペアドステートメントを閉じた後、UPDATE
とvoilaの新しい準備文を使用して2番目のループを実行したときに、各繰り返しに値(ユーザーIDがチェックされています)を保存することでした。それが今見えるようここでは、コードは次のようになります。
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のアドバイスを受け取り、これをより小さく、簡単にダイジェストし、クラス機能を維持するように解説します。もし私がそれを完了したら、私は同じ苦境で他の人を助けることになる結果を示すためにここにフォローアップします。他に誰かが良い解決策を持っているなら、私に知らせてください。私はいつも私のコーディングを改善しようとしています
ありがとう、これは少なくとも同じ状況で誰かを助けることを願っています。
いいえよく、thanks to user934258私は戻って、この/これらの方法のコーディングを再検討しました。彼のアドバイスを受けて、禁止方法から約25行のコードを削除することができました。しかし、余分な引数を渡して余分な引数を渡すだけで、私はコードをunbanメソッドを組み込む多目的にすることができ、不要な繰り返しコードの約77行が削除されました(unbanはそれ以外の禁止はDBのOneの代わりにZeroをチェックし、少し異なるレスポンスを表示しました。)このトピックが参考になるかもしれないあなたの将来については、ここに私のコードの最終製品があります。
スクリプトから呼び出されるメソッド:DB禁止値をチェックする
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 /禁止してDBを更新する方法:
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
のような値のためのチェックボックスとドロップダウンリストに正確にdbからの値が間違っている可能性があります。$user_id
はどれもスリムではありません。
私が他の記事で述べたように、誰かが私がしたことに対してより良い解決策を提供できる場合は、私に知らせてください。
このような素晴らしいコミュニティに感謝します。
あなたの権利では、コードはまだ非常に手続き的です。質問を投稿した後、私は解決策を考え出しましたが、もっと長めのバージョンではありませんでした(私の答えをご覧ください)。私は今あなたのアドバイスを受け取り、もっと小さく、より多くのOOPスタイルの関数に分解できるかどうかを見ていきます。 –