Ошибка ввода PHP / SQL при использовании именных заполнителей

У меня есть следующий PHP PDO-оператор:

$STH = $this->_db->prepare("INSERT INTO UserDetails (FirstName, LastName, Address, City, County, PostCode, Phone, Mobile, Sex, DOB, FundraisingAim, WeeksAim, LengthsAim, HearAboutID, MotivationID, WelcomePackID, ContactPrefID, TitleID) VALUES (:firstName, :lastName, :address, :city, :county, :postCode, :phone, :mobile, :sex, :DOB, :fundraisingAim, :weeksAim, :lengthsAim, :hearAbout, :motivation, :welcomePackPref, :contactPref, :title)"); $STH->execute($userData); 

Где $userDataассоциативный массив. Я дважды проверял имена, и я не понимаю, почему я получаю следующую ошибку:

SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Какую глупую ошибку я сделал?

Solutions Collecting From Web of "Ошибка ввода PHP / SQL при использовании именных заполнителей"

Ваши $userData должны иметь точно такие же заполнители, привязанные вашим заявлением, не больше и не меньше. См. PDOStatement::execute , часть, которая гласит: «Вы не можете связывать больше значений, чем указано».

Вам нужно подготовить свой аргумент для execute() чтобы точно совместить ваши привязки. Это легко с помощью array_intersect_key() если вы правильно упорядочиваете свои массивы. Обычно я обертываю это функцией, которая также будет заботиться о префиксах, как показано ниже:

 // Adds a prefix to a name for a named bind placeholder function prefix($name) { return ':'.$name; } // like 'prefix()', but for array keys function prefix_keys($assoc) { // prefix STRING keys // Numeric keys not included $newassoc = array(); foreach ($assoc as $k=>$v) { if (is_string($k)) { $newassoc[prefix($k)] = $v; } } return $newassoc; } // given a map of datakeyname=>columnname, and a table name, returns an // sql insert string with named bind placeholder parameters. function makeInsertStmt($tablename, $namemap) { $binds = array_map('prefix', array_keys($namemap)); return 'INSERT INTO '.$tablename.' ('.implode(',',$namemap).') VALUES (' .implode(',',$binds).')'; } // returns an array formatted for an `execute()` function makeBindData($data, $namemap) { // $data assoc array, $namemap name->column mapping return prefix_keys(array_intersect_key($data, $namemap)); } // example to demonstrate how these pieces fit together function RunTestInsert(PDO $pdo, $userData) { $tablename = 'UserDetails'; // map "key in $userData" => "column name" // do not include ':' prefix in $userData $namemap = array( 'firstName' => "FirstName", 'lastName' => "LastName", 'address' => "Address", 'city' => "City", 'county' => "County", 'postCode' => "PostCode", 'phone' => "Phone", 'mobile' => "Mobile", 'sex' => "Sex", 'DOB' => "DOB", 'fundraisingAim' => "FundraisingAim", 'weeksAim' => "WeeksAim", 'lengthsAim' => "LengthsAim", 'hearAbout' => "HearAboutID", 'motivation' => "MotivationID", 'welcomePackPref' => "WelcomePackID", 'contactPref' => "ContactPrefID", 'title' => "TitleID", ); $sql = makeInsertStmt($tablename, $namemap); $binddata = makeBindData($userData, $namemap); $pstmt = $pdo->prepare($sql); $pstmt->execute($binddata); } . // Adds a prefix to a name for a named bind placeholder function prefix($name) { return ':'.$name; } // like 'prefix()', but for array keys function prefix_keys($assoc) { // prefix STRING keys // Numeric keys not included $newassoc = array(); foreach ($assoc as $k=>$v) { if (is_string($k)) { $newassoc[prefix($k)] = $v; } } return $newassoc; } // given a map of datakeyname=>columnname, and a table name, returns an // sql insert string with named bind placeholder parameters. function makeInsertStmt($tablename, $namemap) { $binds = array_map('prefix', array_keys($namemap)); return 'INSERT INTO '.$tablename.' ('.implode(',',$namemap).') VALUES (' .implode(',',$binds).')'; } // returns an array formatted for an `execute()` function makeBindData($data, $namemap) { // $data assoc array, $namemap name->column mapping return prefix_keys(array_intersect_key($data, $namemap)); } // example to demonstrate how these pieces fit together function RunTestInsert(PDO $pdo, $userData) { $tablename = 'UserDetails'; // map "key in $userData" => "column name" // do not include ':' prefix in $userData $namemap = array( 'firstName' => "FirstName", 'lastName' => "LastName", 'address' => "Address", 'city' => "City", 'county' => "County", 'postCode' => "PostCode", 'phone' => "Phone", 'mobile' => "Mobile", 'sex' => "Sex", 'DOB' => "DOB", 'fundraisingAim' => "FundraisingAim", 'weeksAim' => "WeeksAim", 'lengthsAim' => "LengthsAim", 'hearAbout' => "HearAboutID", 'motivation' => "MotivationID", 'welcomePackPref' => "WelcomePackID", 'contactPref' => "ContactPrefID", 'title' => "TitleID", ); $sql = makeInsertStmt($tablename, $namemap); $binddata = makeBindData($userData, $namemap); $pstmt = $pdo->prepare($sql); $pstmt->execute($binddata); } 

Преимущество такой абстракции – вам не нужно беспокоиться о самих параметрах привязки.

Как следует из сообщения, в $ userData слишком много или слишком мало записей. Нужно точно соответствовать. Рассмотрите возможность размещения дампа $ userData.

Не уверен, что это по какой-то причине преднамеренно, но у вас есть это:

 EndDate = 1 

В середине имен столбцов.

Кроме того, у вас есть 18 имен столбцов, но только 17 значений. Поэтому сообщение об ошибке правильное.