2013-05-25 52 views
0
<?php 
require_once'config.php'; 
if(isset($_POST['subscribe'])){ 
    $email=$_POST['email']; 

    //check the email if it is already subscribed or not 
    if(strlen($email)>3){    
    $stmt=$mysql->prepare("SELECT * FROM subscribers WHERE email=?"); 
    $stmt->bind_param('s', $email); 
    $stmt->execute(); 
    if($stmt->field_count > 0){ // if not then add 
     unset($mysql); unset($stmt); 
     $mysql=new mysqli(HOST,USER,PASS,DB);  
     $stmt=$mysql->prepare('INSERT INTO subscribers(email) VALUES (?)'); 
     $stmt->bind_param('s', $email); 
     $stmt->execute(); 
     if($stmt->affected_rows>0){ 
     echo "subscribed"; 
     } 
    } else { //else is there 
     echo "Already there"; 
    } 
    } else echo "empty string"; 
} 
?> 

如果我刪除行unset($mysql); unset($stmt);,那麼它會導致致命錯誤:Bind_param Non-Object Error。但是,如果我取消設置,然後重新定義對象,那麼可以正常工作。誰能解釋爲什麼?Mysql bind_param()error

+0

你爲什麼要重新連接?丟失未定義並重新定義。如果失敗,var_dump $ mysql對象。 – Farkie

+0

什麼生產線致命? –

+0

如何使用if($ stmt-> field_count> 0)這意味着一個記錄已經存在它應該是if($ stmt-> field_count == 0) – sAnS

回答

0

警告:這是未經測試的。不過,我認爲重要的是要展示如何以更清晰的方式編寫這些內容。特別是將你的意圖分解成特定的功能,每個功能都會做一件事並返回結果。這將有助於防止您的代碼變得混亂,並且更容易測試每個塊。

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語句是不是很糟糕?難道你沒有正確地從第一條語句中釋放服務器資源嗎?

+0

感謝您的代碼。但其實我想要一個概念性的描述,爲什麼我的代碼發送錯誤,如果我沒有解除。 –

+0

@MohaiminusSakib添加了更多詳細信息,但您可能無法提供足夠的信息來解決您的問題。另請注意,您不需要取消設置;這對於這種情況幾乎肯定是過度的。 –