fetch_obj fetch_array example php mysql arrays pdo associative-array

fetch_array - Error de inserción de PHP/SQL al usar marcadores de posición con nombre



pdo php mysql (3)

Tengo la siguiente declaración 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);

Donde $userData es una matriz asociativa. Revisé los nombres por segunda vez y no entiendo por qué recibo el siguiente error:

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

¿Qué tonto error he cometido?


Como implica el mensaje, $ userData tiene demasiadas o muy pocas entradas. Necesita coincidir exactamente. Considere publicar un volcado de $ userData.


No estoy seguro si esto es intencional por alguna razón, pero tiene esto:

EndDate = 1

En el medio de los nombres de columna.

Además, tiene 18 nombres de columna enumerados, pero solo 17 valores. Entonces el mensaje de error es correcto.


Su $userData debe tener exactamente los mismos marcadores de posición vinculados por su extracto, ni más ni menos. Consulte la documentación de PDOStatement::execute , la parte que dice "No puede enlazar más valores de los especificados".

Necesitas preparar tu argumento para execute() para que coincida con tus enlaces exactamente. Esto es fácil con array_intersect_key() si organiza sus matrices de forma correcta. Normalmente envuelvo esto en una función que también se encarga de prefijar, como a continuación:

// 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); }

El beneficio de una abstracción como esta es que no necesita preocuparse por los parámetros de enlace en sí mismos.