Предостережение: это не проверено. Однако я подумал, что важно продемонстрировать, как писать это более чистым способом. В частности, разложите свое намерение на определенные функции, каждый из которых делает одно и возвращает результат. Это поможет сохранить ваш код в запутанности и облегчит тестирование каждого куска на своем собственном.
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