2013-05-25 4 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() ошибка

+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 Добавил более подробную информацию, но вы можете не предоставлять достаточную информацию здесь, чтобы решить вашу проблему. Также обратите внимание, что вам не нужно отменять; это почти наверняка излишним для этой ситуации. –

Смежные вопросы