mySql and php add to database - php

I've been stuck on this for hours. I have to manipulate a database with a website using php. I'm trying to add data from a form to my database but it gives me :
PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in...
This is what's creating the problem.
$sqlQuery = 'INSERT INTO succursale(adresse, ouverture, fermeture, ouvert_raison) VALUES (:adresse, :ouverture, :fermeture, :ouvert_raison)';
$req = $conn->prepare($sqlQuery);
$req-> execute(array($_POST['adresse'], $_POST['ouverture'], $_POST['fermeture'], $_POST['ouvert_raison']));;
I've looked for people with a similar problem but the answers given do not match with my situation.

You are using named placeholder in your prepared statement. This means you'll need to pass those as an associative index. Otherwise the statement will not know which value to bind to the placeholder
$req-> execute(array(
':adresse' => $_POST['adresse'],
':ouverture' => $_POST['ouverture'],
':fermeture' => $_POST['fermeture'],
':ouvert_raison' => $_POST['ouvert_raison'],
));
If you don't want to do this, you can change the named placeholders to a ?
$sqlQuery = 'INSERT INTO succursale(adresse, ouverture, fermeture, ouvert_raison) VALUES (?, ?, ?, ?)';

Related

How a placeholder in a prepared statement calls a value in an associative array?

The code is already working, but I couldn't fully understand how the place-holders is calling the value of an associative array. I already read the documentation but without success to understand it.
$app['dtb'] -> insert('users', [
'name' => $_POST['name']
'age' => $_POST['age], ]);`
My insert method:
$sql = sprintf(
'insert into %s (%s) values (%s)',
$table,
implode(', ' , array_keys($parameters)),
':' . implode(', :' , array_keys($parameters))
);
So this would result on something like this:
insert into users (name) values (:name)
If i'm not using any bind_param how it identify that :name is the value of the key name ?
bind_param is a mysqli function. That driver does not support named placeholders. You must be using PDO, PDO has a bindparam function that is similar. It also allows you to just pass an array to the execute function. This binds the values in the order they appear if unnamed placeholders were used (?), or by the keys of the array if the placeholders were named (:...). I'd guess you are passing $parameters to the execute function.

bind_param number of elements doesn't match number of element array

hello i've got a question about bind_param every code is works but not this one...probably dumb question..
$key = "`".implode("`, `",array_keys($notifikasi))."`";
echo $value = "'".implode("', '",array_values($notifikasi))."'";
$query = $dbcon->prepare("INSERT INTO `notifikasi` ($key) VALUES ($value)");
$query->bind_param("iiiis",$value);
$query->execute();
i've echo the value :
'1','1','2','3','profile.php?confirm=33'
i've put any number on bind_param still got this error:
mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables
anyone can answer my misunderstanding?
[EDIT]
nevermind, i've found the solution :
use call_user_func_array()
mysqli bind_param for array of strings
thanks
The problem is you are trying to bind parameters when you didn't add any placeholder for them.
You should never trust user's input so I would suggest you not to populate column names from the input. I would fix column names in query:
$notifikasi = [1, 2, 'profile'];
$query = $dbcon->prepare("INSERT INTO `notifikasi` (col1, col2, col3) VALUES (?, ?, ?)");
$query->bind_param("iis", $notifikasi);

Error:sqlstate[hy093]: invalid parameter number

I can convert the echo'ed output in to an SQL statement that executes in phpMyAdmin going...
From this:
INSERT INTO crumbs (ip_address,ip_address_2,device_info,user_id,connections) VALUES(?,?,?,?,?)Value:'00.000.000.000', '00.000.000.000', 0,0000, 1
Into this:
INSERT INTO crumbs (ip_address,ip_address_2,device_info,user_id,connections) VALUES('00.000.000.000', '00.000.000.000', 0,0000, 1)
It inserts the data in to the DB, no errors, however it executes through PHP-PDO...
With:
SQLSTATE[HY093]: Invalid parameter number
The code:
$columns = '('.implode(',', array_keys($user_connection)).''.",user_id,connections)";
$inserts="(".implode(',',array_fill(0,count($user_connection)+2, '?')).")";
$values = implode(', ',($user_connection)).",$user_id, 1";
$sql_insert = "INSERT INTO crumbs ".$columns." VALUES".$inserts;
$stmt = $this->_db->prepare($sql_insert);
$stmt->execute(array($values));
Edit-Adding $user_connection
$user_connection [ 'ip_address'] = "'".$_SERVER['REMOTE_ADDR']."'";
$user_connection [ 'ip_address_2']="'".$_SERVER['HTTP_X_FORWARDED_FOR']."'";
$user_connection ['device_info']=0;
The error occurs during the execution of the SQL code. I've gone over all the examples and found nothing that's equivalent, I'm thinking it's something simple I'm missing (a rule?) since the code executes locally.
You have to do something like this:
// ..code..
$values = $user_connection;
$values[] = $user_id;
$values[] = 1;
// ..code..
$stmt->execute($values);
Explanation of the problem:
When you have multiple ? placeholders, you can pass each value to be bounded as the values of an array (See Example #3 from the manual).
Now, since you are using implode, $values will be a single string, something like
'192.168.0.1', '8.8.8.8', 0, 'userid', 1
That means that when you call execute(array($values)), it will, in fact, bound it like this (representation-only, it's not really like this)
INSERT INTO crumbs (ip_address,ip_address_2,device_info,user_id,connections) VALUES ("'192.168.0.1', '8.8.8.8', 0, 'userid', 1", ?, ?, ?, ?)
because you only sent and array that has one value: the implosion of the other array. Since you didn't provide the same amount of values (1) as you have placeholders (5), you end up with
Invalid parameter number

Insert_id is null when used directly in next prepared statement

Finally getting around to learning prepared statements. I'm getting a maddening error when trying to run a pair of simple inserts:
$p_stmt = $mysqli->prepare("INSERT INTO ww_pages (page_key) VALUES (?)");
$p_stmt->bind_param('s', $page_key);
$p_stmt->execute();
$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->bind_param('issss', $p_stmt->insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s"));
$pv_stmt->execute();
echo $pv_stmt->error;
The echo $pv_stmt->error; gives this error: Column 'page_id' cannot be null
As I'm sure you can interpret, I'm trying to assign page_id the insert_id of the first statement. I'm 100% sure that this value is non-null, and returns an integer value. I tested it directly with this:
echo "NEW ID: ".$p_stmt->insert_id."::".is_int($p_stmt->insert_id);
The output? NEW ID: 13::1
What am I doing wrong? Why am I getting "column cannot be null" when the column isn't null? The only solutions I can find online are involving unexpectedly null values.
The solution to this problem is to save the value of the property $p_stmt->insert_id in a variable and bind that variable instead. You have to do the same for trim() and date() anyway, albeit for different reasons.
$insert_id = $p_stmt->insert_id;
$page_content = trim($_POST["page_content"]);
$version_notes = trim($_POST["version_notes"]);
$date = date("Y-m-d H:i:s");
$pv_stmt->bind_param('issss', $insert_id, $page_title, $page_content, $version_notes, $date);
As of PHP 8.1, you can also bind by value when you pass all values as an array to execute(). No temporary variables are needed.
$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->execute([$p_stmt->insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s")]);
Explanation of why binding insert_id doesn't work
The reason why binding mysqli_stmt::insert_id results in a value NULL becomes a little bit more clear on PHP 8.1. Since this version, PHP has added property types to most of built-in classes, even for properties that aren't true properties but are __get() calls instead. With PHP 8.1 you get the following error:
Fatal error: Uncaught Error: Cannot access uninitialized non-nullable property mysqli_stmt::$insert_id by reference
PHP claims that the property is uninitialized and you can't have a reference to an uninitialized property. You can mimick the same behaviour with this code:
class A {
public int $insert_id;
}
$a = new A();
$stmt = $mysqli->prepare('SELECT ?');
$stmt->bind_param('s', $a->insert_id);
$stmt->execute();
For the same reason, assignment by reference to a variable would not work:
$foo =& $p_stmt->insert_id;
But you might ask, how can the property be uninitialized when you can read its value without any issue. The answer is because internally these properties are implemented using function calls in PHP, similar to __get() magic method. The value is read from the internal memory of mysqlnd, not from the property itself. Properties of mysqli are just a facade to the underlying client library mysqlnd.
Put the value of insert_id into a temporary variable and bind that variable instead.
$p_stmt = $mysqli->prepare("INSERT INTO ww_pages (page_key) VALUES (?)");
$p_stmt->bind_param('s', $page_key);
$p_stmt->execute();
$insert_id = $p_stmt->insert_id;
$pv_stmt = $mysqli->prepare("INSERT INTO ww_page_versions (page_id, page_title, page_content, version_notes, version_timestamp) VALUES (?, ?, ?, ?, ?)");
$pv_stmt->bind_param('issss', $insert_id, $page_title, trim($_POST["page_content"]), trim($_POST["version_notes"]), date("Y-m-d H:i:s"));
$pv_stmt->execute();

bind_param getting an error (seems illogical to me)

This doesn't seem to make sense to me. Is this ACTUALLY wrong??? I've looked at other people's work, and they have that same type of bind_param as me, like in this example:
php, mysqli-stmt.bind-param]: Number of elements in type definition string doesn't match number of bind variables
I have 23 here, AND 23 values (yes, I counted individually, even pressing enter on dreamweaver to make sure). And to be safe, I even tried with 46:
$stmt= $con->prepare("INSERT INTO form_corpo_test (compagnie, telephone, site_web, texte_fr, texte_en, categories, profil_exposant, stands_du_manufacturier, pourcentage_quebec, pourcentage_canada, pourcentage_usa, pourcentage_autre, exporte, exporte_souhaite, produits_vert, nouveau_produits, nom, courriel, telephone_ressource, personne_ressource_c_toi, autre_personne_ressource, autre_courriel, autre_telephone)
VALUES
('$_POST[company]','$_POST[phone]','$_POST[website]','$_POST[messagefr]','$_POST[messageen]','$str','$_POST[profession]','$_POST[manufacturiers_stand]','$_POST[percent_quebec]','$_POST[percent_canada]','$_POST[percent_usa]','$_POST[percent_autre]','$_POST[bt_export]','$_POST[bt_export_souhaite]','$_POST[bt_prod_verts]','$_POST[bt_new_prod]','$_POST[name]','$_POST[email]','$_POST[resource_phone]','$_POST[personne_ressource]','$_POST[backup_name]','$_POST[backup_email]','$_POST[backup_phone]')");
$stmt->bind_param("sssssssssssssssssssssss", $compagnie, $telephone, $site_web, $texte_fr, $texte_en, $categories, $profil_exposant, $stands_du_manufacturier, $pourcentage_quebec, $pourcentage_canada, $pourcentage_usa, $pourcentage_autre, $exporte, $exporte_souhaite, $produits_vert, $nouveau_produits, $nom, $courriel, $telephone_ressource, $personne_ressource_c_toi, $autre_personne_ressource, $autre_courriel, $autre_telephone);
And then I tried this (since phone numbers are integers)
sissssssiiiissssssisssi
Both outputs THIS error:
Warning: mysqli_stmt::bind_param() [mysqli-stmt.bind-param]: Number of
variables doesn't match number of parameters in prepared statement in
/home/product/public_html/sidim.com/formulaires/processForm-test.php
on line 77
EDIT 3
I have this at the moment:
$con->query("INSERT INTO form_corpo_test SELECT * FROM *");
$stmt = $con->prepare("INSERT INTO form_corpo_test VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
$stmt->bind_param('sissssssiiiissssssisssi', $compagnie, $telephone, $site_web, $texte_fr, $texte_en, $categories, $profil_exposant, $stands_du_manufacturier, $pourcentage_quebec, $pourcentage_canada, $pourcentage_usa, $pourcentage_autre, $exporte, $exporte_souhaite, $produits_vert, $nouveau_produits, $nom, $courriel, $telephone_ressource, $personne_ressource_c_toi, $autre_personne_ressource, $autre_courriel, $autre_telephone); // bind $compagnie etc. to the parameter
This still errors this outputs
Fatal error: Call to a member function bind_param() on a non-object in
/home/product/public_html/******/*******/processForm-test.php on line
83
This refers to this:
$stmt->bind_param('sissssssiiiissssssisssi', $compagnie, $telephone, $site_web, $texte_fr, $texte_en, $categories, $profil_exposant, $stands_du_manufacturier, $pourcentage_quebec, $pourcentage_canada, $pourcentage_usa, $pourcentage_autre, $exporte, $exporte_souhaite, $produits_vert, $nouveau_produits, $nom, $courriel, $telephone_ressource, $personne_ressource_c_toi, $autre_personne_ressource, $autre_courriel, $autre_telephone); // bind $compagnie etc. to the parameter
If there is anything wrong so far, lemme know by all means. I will check out u_mulder's posts more in depth now.
In php manual it is shown how to bind params:
$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);
See that question marks? Every question mark will be replaced with a parameter from bind_param. So, your query should look like:
$stmt= $con->prepare("INSERT INTO form_corpo_test (compagnie,... autre_telephone) VALUES (?, ?, ?, ?, ?, ?, ?, ....."); // 26 ?-signs
$stmt->bind_param("sssssssssssssssssssssss", $compagnie, $telephone.. ); // your params here

Categories