警告:這是未經測試的。不過,我認爲重要的是要展示如何以更清晰的方式編寫這些內容。特別是將你的意圖分解成特定的功能,每個功能都會做一件事並返回結果。這將有助於防止您的代碼變得混亂,並且更容易測試每個塊。
require_once'config.php';
//It is always good to declare stuff like this in a central place
//That way they're easy to change, and you change it everywhere you have that express intent
$SQL_FIND_SUBSCRIPTION = "SELECT * FROM subscribers WHERE email=?";
$SQL_NEW_SUBSCRIPTION = "INSERT INTO subscribers(email) VALUES (?)";
//Functions make testing easy!
static function attemptSubscription($postValues, &$returnMsg) {
if ( isset($postValues['subscribe'])
&& isset($postValues['email']) //be sure to validate both!
{
if (isValidEmail($postValues['email'])) {
subscribe($email);//this syntax may be off.
} else {
$returnMsg = "A valid email address must be provided.";
return false;
}
} else {
$returnMsg = "No subscription was attempted.";
return false;
}
}
//Returns true if the passed parameter is a valid email
static function isValidEmail($email) {
//left as an exercise for the reader.
}
//Assumes a valid email address is being passed
static function subscribe($email, &$returnMsg) {
global $mysql; //sadly, this is the cleanest way possible without using a class.
$stmt=$mysql->prepare($SQL_FIND_SUBSCRIPTION);
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->store_result(); // This lets you reuse stmt
if($stmt->field_count > 0){
//Subscription already exists
$returnMsg = "This subscription already exists.";
return true;
} else {
//Subscription must be added
return addNewSubscription($email, $returnMsg);
}
}
static function addNewSubscription($email, &$returnMsg) {
global $mysql; // :(
$stmt=$mysql->prepare($SQL_NEW_SUBSCRIPTION);
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->store_result();
if($stmt->affected_rows>0){
$returnMsg = "New subscription successful!";
return true;
} else {
$returnMsg = "New subscription failed.";//you can add more info here if you want
return false;
}
$stmt->close();
}
//now actually execute
$resultMsg = "";
if (attemptSubscription($_POST, $resultMsg)) {
echo "Success! ".$resultMsg;
} else {
echo "Oh no! Failure! ".$resultMsg;
}
// ?> Note that eliding this will help remove nasty hidden characters from the rendered html
查看store_result瞭解更多。
使用這種配置,您可以驗證單個命令是否正常工作,而不必依賴於首先執行它們嵌套的結構。特別是,驗證第二個sql查詢至關重要:非綁定錯誤是通常是因爲找不到列或表格。然而,這就是說,要認識到prepare()
語句的作用是發送一個查詢到服務器來檢查語法;該查詢永遠不會被重新發送,而是保持「加載」在服務器中,直到您告訴它(以另一種說法)擺脫它。當您隨後綁定參數時,該參數將發送到服務器並放入可用插槽(?
)。因爲這個模型,您可以有效地多次執行此查詢。
請注意,如果服務器上的查詢沒有未綁定的新參數插槽,則綁定嘗試將失敗。如果服務器上的查詢試圖引用不可用的變量(如列名稱),則在此步驟中也會失敗。
從您提供的詳細信息中確切知道問題的具體位置並不清楚,但是如果您以更清晰的方式編寫代碼,調試這些問題將變得更加容易:您的第二個sql語句是不是很糟糕?難道你沒有正確地從第一條語句中釋放服務器資源嗎?
你爲什麼要重新連接?丟失未定義並重新定義。如果失敗,var_dump $ mysql對象。 – Farkie
什麼生產線致命? –
如何使用if($ stmt-> field_count> 0)這意味着一個記錄已經存在它應該是if($ stmt-> field_count == 0) – sAnS