Как правильно построить SQL-запрос в PHP скрипт?

Я пытаюсь создать SQL-запрос для вставки информации о пользователе в базу данных. Переменные $fname и $lname содержат правильные значения ( "John" и "Doe" ), но запрос терпит неудачу. Вот мой код:

$fname = $_POST['first_name'];
$lname = $_POST['last_name'];  
$sql = "INSERT INTO users (fname, lname) VALUES ($fname, $lname)";
mysqli_query($conn, $sql);

после проверки сообщения об ошибке я обнаружил, что этот запрос завершился с ошибкой, говоря

Неизвестный столбец "Джон" в списке полей

Как правильно включить переменные в SQL-запрос, чтобы он запускался без ошибок?

  • Этот вопрос связан не с синтаксисом SQL, с которым я знаком, а с правилами создания запроса динамически с использованием переменных в PHP script.
  • Мне не нужен быстрый патч, который устраняет только немедленную ошибку, но это современное решение, которое также безошибочно и безопасно.

Ответ 1

Самый ошибочный способ добавить переменную в SQL-запрос - добавить ее через подготовленный оператор.

Очень важно понять, что просто добавить кавычки вокруг переменной недостаточно и в конечном итоге приведет к бесчисленным проблемам, от синтаксических ошибок до SQL-инъекций. С другой стороны, из-за самой природы подготовленных операторов это пуленепробиваемое решение, которое делает невозможным введение какой-либо проблемы через переменную данных.

Таким образом, для каждого выполняемого вами запроса, если будет использоваться хотя бы одна переменная, вы должны подставить ее заполнитель, затем подготовить свой запрос, а затем выполнить его, передав переменные отдельно.

Прежде всего, вы должны изменить свой запрос, добавив вместо переменных переменные. Ваш запрос станет следующим:

$sql = "INSERT INTO users (fname, lname) VALUES (?, ?)";

Затем вам придется подготовить его, связать переменные и выполнить:

$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, "ss", $fname, $lname);
mysqli_stmt_execute($stmt);

Как вы можете видеть, это всего три простых команды:

  • prepare(), где вы отправляете запрос с заполнителями
  • bind_param, где вы отправляете строку с типами ( "s" - для строки, и вы можете использовать ее для любого типа на самом деле), а не для фактических переменных.
  • и выполните()

Таким образом, вы всегда можете быть уверены, что ни одна синтаксическая ошибка SQL не может быть вызвана данными, добавленными в запрос! В качестве бонуса этот код также пуленепробиваемый SQL-инъекции!

Есть щепотка соли, хотя, поскольку выполнение запроса SELECT с подготовленными операциями mysqli может быть более сложным. Поэтому я настоятельно рекомендую выбрать PDO в качестве драйвера базы данных по многим причинам.