Ошибка Invalid parameter number: parameter was not defined ()


Эта ошибка сигнализирует о проблемах с плейсхолдерами. Под словом parameter здесь имеется в виду именно он. То есть, "parameter was not defined" означает, что мы пытаемся привязать к запросу плейсхолдер, которого в нем нет.

Например, мы определили в запросе плейсхолдер, но ошиблись при его написании его имени в массиве:

$stmt = $db->prepare('UPDATE t SET name = : WHERE id = :name');
$stmt->execute(['mane' => $name, 'id' => $id]));


PDO попытается найти в запросе плейсхолдер с именем 'mane', не найдет его, и выдаст эту самую ошибку!

Кстати, вопреки распространенному заблуждению, наличие двоеточия в индексе массива совершенно не обязательно и причиной ошибки быть не может.

При исправлении данной ошибки следует обратить внимание на следующие проблемы:

1. Самая распространённая: пользователь по привычке берет плейсхолдеры в кавычки. Этого делать ни в коем случае нельзя - ПДО примет их за обычные строки, и в итоге не найдет в запросе ни одного плейсхолдера.

2. Тоже весьма частая причина: опечатки в именованных плейсхолдерах. Скажем, в запросе user_name, а в передаваемых данных - username. Также следует помнить что имена плейсхолдеров чувствительны к регистру.

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

4. Также следует помнить, что для имен плейсхолдеров поддерживаются только латинские буквы, цифры и символ подчеркивания. Так что если у вас в имени плейсхолдера есть русская буква, то это послужит причиной все той же ошибки.

5. Если строка запроса формируется динамически, то при появлении таких ошибок необходимо применить навыки отладки - а именно, вывести сформированный программой SQL и посмотреть, соответствует ли он ожидаемому. Кстати, при динамическом формировании запроса следует обратить внимание на защиту от инъекции имен полей. Имена обязательно должны быть прописаны в скрипте, и попадать в запрос только в из этого заранее подготовленного списка!

Если вы все равно не можете найти ошибку - пишите свой код в комментариях, разберемся!