I've a problem with PDO prepared statements using mysql.
When the query is executed it will save into the preposed table the placeholders that I've binded using the bindParam() method.
Here is the code and here is a screen of the result of the execution of the query. How i can solve this embaracing problem? I'm a newbie on PDO!
PHP (This is the controller that is called using ajax).
if(isset($_POST['code'])){
$code = filter_var($_POST['code'],FILTER_SANITIZE_STRING);
$qty = filter_var($_POST['quantity'],FILTER_SANITIZE_STRING);
$brand = filter_var($_POST['brand'],FILTER_SANITIZE_STRING);
$article_name = filter_var($_POST['artName'],FILTER_SANITIZE_STRING);
$price = filter_var($_POST['price'],FILTER_SANITIZE_STRING);
$article_type = filter_var($_POST['artType'],FILTER_SANITIZE_STRING);
$note = filter_var($_POST['note'],FILTER_SANITIZE_STRING);
$save = $core->insert_article($code,$qty,$brand,$article_name,$price,$article_type,$note);
if($save){
echo 'ok';
} else {
echo 'error';
}
}
PHP 2 (this is the function of the class who manage all the database operations)
public function insert_article($code,$qty,$brand,$article_name,$price,$article_type,$note){
$db = $this->init_db();
$sql = "INSERT INTO products (cod_articolo, pezzi_disponibili, marca, nome_articolo, prezzo, tipologia_articolo, note) VALUES (':cod_articolo',':pezzi_disponibili',':marca',':nome_prodotto',':prezzo',':tipologia_articolo',':note')";
$stmt = $db->prepare($sql);
$stmt->bindParam(':cod_articolo',$code,PDO::PARAM_STR);
$stmt->bindParam(':pezzi_disponibili',$qty,PDO::PARAM_STR);
$stmt->bindParam(':marca',$brand,PDO::PARAM_STR);
$stmt->bindParam(':nome_articolo',$article_name,PDO::PARAM_STR);
$stmt->bindParam(':prezzo',$price,PDO::PARAM_STR);
$stmt->bindParam(':tipologia_articolo',$article_type,PDO::PARAM_STR);
$stmt->bindParam(':note',$note,PDO::PARAM_STR);
if($stmt->execute()){
echo 'ok';
} else {
echo 'error';
}
}
This is the screen of the results after that the query is executed
table after query execution
Try removing the single quotes surrounding the binding part
$sql = "INSERT INTO products (cod_articolo, pezzi_disponibili, marca, nome_articolo, prezzo, tipologia_articolo, note) VALUES (:cod_articolo,:pezzi_disponibili,:marca,:nome_prodotto,:prezzo,:tipologia_articolo,:note)";
Related
I am some confused because some people write PHP code like this for upload data.
But my instructor used $query and $link always to upload and retrieve data from SQL.
<?php
include 'connection.php';
function reg_in() {
if (isset($_POST['submit'])) {
$name = $_POST['name'];
$email = $_POST['email'];
$mob = $_POST['mobile'];
$check_in = $_POST['in'];
$check_out = $_POST['out'];
$rm = $_POST['room'];
$room_type = $_POST['type'];
// Problem start from here
if (mysql_query("INSERT INTO `book` (`name`,`email`,`mobile_no`,`check_in`,`check_out`,`room`,`room_type`) VALUES ('$name','$email','$mob','$check_in','$check_out','$rm','$room_type')")) {
header('Location: C:/wamp/www/project/payment.html');
} else {
echo mysql_error();
}
}
}
if (isset($_POST['submit'])) {
reg_in();
//echo ' succesfully inserted';
} else {
echo 'Not book';
}
MySQL (by my instructor):-
<?php
$link = mysqli_connect("myserver.com", "test", "sunil7117", "test");
if (mysqli_connect_error()) {
die("please give correct permision");
}
//Is both are same!
//$query="INSERT INTO user(email,password) VALUES ('shivanandcpr25#gmail.com','sunil7117')";
$query = "UPDATE user SET email='test#gmail.com' WHERE email='abc#gmail.com' LIMIT 1";
echo mysqli_query($link, $query);
echo "<br>";
$query = "SELECT * FROM user";
if ($result = mysqli_query($link, $query)) {
echo "welcome to database<br>";
$row = mysqli_fetch_array($result);
echo "my E-mail id is <strong> ".$row[1]. "</strong> and passoword is <strong>".$row[2]."</strong>";
}
Neither!
Your first example uses function which has been removed from PHP years ago. mysql_query() does not exist and should not be used anymore. The reason why it was removed is that you should use prepared statements instead. They are provided by either mysqli or PDO extensions.
Your second example is better, but it is way too messy.
You should not echo mysqli_query. There's nothing useful to be printed out from this function.
Get into a habit of using prepared statements all the time and use placeholders for variable data. As of now your queries are constant, but using prepared statements is still a good practice in case you need to add a parameter later on.
Avoid using functions like mysqli_fetch_array(). Iterating the result option one by one is messy and rarely useful.
Never check the return value of mysqli calls. It's pointless. Enable error reporting instead. See How to get the error message in MySQLi?
Always set the correct charset. It should be utf8mb4 99% of the time.
The SQL query can be saved in a separate variable, but what's the point? You are only going to pass it as an argument to the query function. There's no need to use an intermediate variable.
Don't use mysqli. You should use PDO instead. If you have to use mysqli, then create a simple wrapper function or class for this purpose and execute your generic function instead of messing around with mysqli functions.
Here is an example of how I would do it. First I enable error reporting for mysqli, I open the connection and set the charset. Then I declare a function which takes 3 parameters and returns an array. First parameter is your database connection you have just opened. Second is your SQL query with placeholders if there are any. Third is optional and it is an array of values to be bound to the placeholders as parameters. This function works for all kind of SQL queries. The rest of the code becomes really simple.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = new mysqli("myserver.com", "test", "sunil7117", "test");
$link->set_charset('utf8mb4'); // always set the charset
/**
* Executes an SQL query on the database.
*
* #param \mysqli $mysqli
* #param string $query e.g. SELECT * FROM users WHERE username=?
* #param array $params An array of parameters to be bound in the given order to the placeholders in SQL
* #return array
*/
function prepared_query(\mysqli $mysqli, string $query, array $params = []): array {
$stmt = $mysqli->prepare($query);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
prepared_query($link, "UPDATE user SET email='test#gmail.com' WHERE email='abc#gmail.com' LIMIT 1");
echo "<br>";
$result = prepared_query($link, "SELECT * FROM user");
echo "welcome to database<br>";
if ($result) {
$row = $result[0];
echo "my E-mail id is <strong> ".$row[1]. "</strong> and passoword is <strong>".$row[2]."</strong>";
}
This is my code I have to insert an array each value in the insert statement
if(isset($_POST['add'])){
$batch = $_POST['batch'];
$course = explode(':', $_POST['course']);
$cid = $course[0];
$rowCount = count($_POST['branch']);
$branch = implode(',', $_POST['branch']);
$semester = $_POST['sem'];
$day = $_POST['day'];
$hour = $_POST['hour'];
for($i=0;$i<$rowCount;$i++){
$description = $_POST['branch'][$i];
$sql. = "INSERT INTO batch (batch,bdescription,branch,course,semester,day,hour,user) VALUES ('$batch','$description',$i,'$cid','$semester','$day','$hour','$usnid');";
}
if($conn->query($sql)){
$_SESSION['success'] = 'batch added successfully';
}
else{
$_SESSION['error'] = $conn->error;
}
}
Please help thanks
You can't execute multiple queries with a single call to $conn->query().
Change your query so it's just a single INSERT statement with multiple lists of values after VALUES.
$sql = "INSERT INTO batch (batch,bdescription,branch,course,semester,day,hour,user) VALUES "
for($i=0;$i<$rowCount;$i++){
$description = $_POST['branch'][$i];
$sql. = "('$batch','$description',$i,'$cid','$semester','$day','$hour','$usnid'),";
}
$sql = substr($sql, 0, -1); // remove last comma
You should also use $conn->real_escape_string() to escape all the inputs, to protect against SQL injection (it would be even better to do that with a prepared statement, but it's difficult to make a prepared statement in mysqli with dynamic parameters).
Barmar is correct, you can't execute multiple SQL statements with query(). There's mysqli_multi_query(), but there's hardly ever a justification for using that. The former Engineering Director for MySQL once told me unequivocally, "there's no reason for multi-query to exist."
You should use parameters instead of copying $_POST variables directly into your SQL strings. It's not hard, in fact it makes code easier than fiddling with confusing quotes-within-quotes and mysqli_real_escape_string() and so on.
I wouldn't bother with trying to insert multiple tuples in a single INSERT statement. How many branches can possibly be in a single POST? A few dozen at most? Not enough to make it necessary to make the INSERT into a single statement. So just call execute() for a prepared INSERT, once for each row.
$sql = "INSERT INTO batch
SET batch=?, bdescription=?, branch=?, course=?, semester=?,
day=?, hour=?, user=?";
$stmt = $conn->prepare($sql) or die($conn->error);
$description = '';
$stmt->bind_param('ssssssss', $batch, $description, $i, $cid, $semester, $day, $hour, $usnid);
for($i=0;$i<$rowCount;$i++){
$description = $_POST['branch'][$i];
$stmt->execute() or die($stmt->error);
}
Read the manual for https://www.php.net/manual/en/mysqli-stmt.bind-param.php for more code examples.
This is how I Fixed My Code. I Used for loop
if(isset($_POST['addstd'])){
$rowCount = count($_POST['student']);
for($i=0;$i<$rowCount;$i++){
$stdid = $_POST['student'][$i];
$course = $_POST['course'][$i];
$batch = $_POST['batch'][$i];
$branch = $_POST['branch'][$i];
//insert students into attendance table
$sqlsel = "SELECT year,student_id, student_rollno,firstname,lastname, branch,active, nr FROM student WHERE student.student_id = '$stdid' AND student.branch = '$branch'";
$querysel = $conn->query($sqlsel) or die($conn->error);
$rowsel = $querysel->fetch_assoc();
if($rowsel !== null){
$year = $rowsel['year'];
$rollno = $rowsel['student_rollno'];
$active = $rowsel['active'];
$branch = $rowsel['branch'];
$name = $rowsel['firstname'].$rowsel['lastname'];
$sql = "INSERT IGNORE INTO class (year,regno, rollno,name, programme,coursecode,batch,user,active,count) VALUES ('$year','$stdid','$rollno','$name','$branch','$course','$batch','$usnid','$active','$i');";
if($conn->query($sql)){
$_SESSION['success'] = 'Students Added To Batch Successfully';
}
else{
$_SESSION['error'] = $conn->error;
}
}
else{
continue;
}
}
}
else{
$_SESSION['error'] = 'Fill up add form first';
}
Here's the problematic PHP function:
//Get data associated with $criteria from db
function getUserData($criteria, $value) {
//obtain user data from db based on $criteria=$value
global $pdo;
//echo $criteria . " " . $value;
try {
$sql = 'SELECT id, first, last, email, userid FROM users WHERE :criteria= :value';
//var_dump($sql);
$st = $pdo->prepare($sql);
$st->bindValue(':criteria', $criteria);
$st->bindValue(':value', $value);
$st->execute();
}
catch (PDOException $ex) {
$error = "Failed to obtain user data.";
$errorDetails = $ex->getMessage();
include 'error.html.php';
exit();
}
$row = $st->fetch();
//var_dump($row);
if ($row)
{
$userdata = array();
$userdata['id'] = $row['id'];
$userdata['first'] = $row['first'];
$userdata['last'] = $row['last'];
$userdata['email'] = $row['email'];
$userdata['userid'] = $row['userid'];
return $userdata;
}
return FALSE;
}
I use this function to return a whole row of data associated with specific column in it.
When used at it's current state, with a call like that getUserData("email", "John_Stewart_2013"), it returns false, meaning an empty result, while the same query runs fine in MySQL CLI.
If I, on the other hand, substitute the query string $sql with :
$sql = "SELECT id, first, last, email, userid FROM users WHERE $criteria='$value'";
And comment out the bindValue calls, Every thing runs fine in PHP, and the query returns as desired.
But the problem is, those function arguments are user-submitted form data, meaning the solution is vulnerable to SQL Injection.
What's wrong here in the first query form?
You can't use bindValue with column names I'm afraid.
If you think about what a prepared statement is, this should become more obvious. Basically, when you prepare a statement with the database server, it creates an execution plan for the query beforehand, rather than generating it at the time of running the query. This makes it not only faster but more secure, as it knows where it's going, and the datatypes that it will be using and which are going to be input.
If the column/table names were bindable in any way, it would not be able to generate this execution plan, making the whole prepared statement idea somewhat redundant.
The best way would be to use a hybrid query like so:
$sql = "SELECT id, first, last, email, userid FROM users WHERE $criteria = :value";
I'm going to hope that the $criteria column isn't entirely free form from the client anyway. If it is, you'd be best limiting it to a specific set of allowed options. A simplistic way to do would be to build an array of allowed columns, and check if it's valid with in_array, like so:
$allowed_columns = array('email', 'telephone', 'somethingelse');
if (!in_array($criteria, $allowed_columns))
{
$error = "The column name passed was not allowed.";
$errorDetails = $ex->getMessage();
include 'error.html.php';
exit;
}
In my PHP script I am trying to use variable name as the table name in a MySQL statement, but when I use the variable as the table name it give me a syntax error if no ` are used and says Incorrect Table Name '' when ` are used. The code is attached below
function toQuery($tblName){
$t = "testtitle";
$art = "testarticle";
$auth = "testauthor";
return "INSERT INTO `$tblName` VALUES ('$t', '$art', '$auth', null)";
}
mysql_connect("localhost","testuser","pass123");
mysql_query("Use `test_schema`");
if(mysql_query(toQuery("test_table"))){
echo "Query: ".toQuery("test_table")." was run.";
}else{
echo "Query: ".toQuery("test_table")." was not run. ".mysql_error();
}
When I use the variable $tblName variable it echos an identical query to if i just put test_table straight in the query returned, but the one with out the variable in query executes properly.
you don't use mysql_select_db() . try this :
function toQuery($tblName){
$t = "testtitle";
$art = "testarticle";
$auth = "testauthor";
return "INSERT INTO `$tblName` VALUES ('$t', '$art', '$auth', null)";
}
mysql_connect("localhost","testuser","pass123");
mysql_select_db('dbname');
mysql_query("Use `test_schema`");
if(mysql_query(toQuery("test_table"))){
echo "Query: ".toQuery("test_table")." was run.";
}else{
echo "Query: ".toQuery("test_table")." was not run. ".mysql_error();
}
replace your database name eith dbname
I think You are choosing the database outside the function. It might be because of the variable accessibility.
Try putting the line mysql_query("Usetest_schema"); inside function.
function toQuery($tblName){
$t = "testtitle";
$art = "testarticle";
$auth = "testauthor";
mysql_query("Use `test_schema`");
return "INSERT INTO `$tblName` VALUES ('$t', '$art', '$auth', null)";
}
I am trying to insert multiple rows into MySQL DB using PHP and HTML from. I know basic PHP and searched many examples on different forums and created one script however it doesn't seem working. Can anybody help with this. Here is my script:
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
}
$sql .= "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result) {
die('Error: ' . mysql_error());
} else {
echo "$row record added";
}
MySQL can insert multiple rows in a single query. I left your code as close as possible to the original. Keep in mind that if you have a lot of data, this could create a large query that could be larger than what MySQL will accept.
include_once 'include.php';
$parts = array();
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$parts[] = "('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
}
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES " . implode(', ', $parts);
$result = mysql_query($sql, $con);
Please try this code. Mysql query will not accept multiple insert using php. Since its is a for loop and the values are dynamically changing you can include the sql insert query inside the for each loop. It will insert each rows with the dynamic values. Please check the below code and let me know if you have any concerns
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result)
{
die('Error: ' . mysql_error());
}
else
{
echo "$row record added";
}
}
I would prefer a more modern approach that creates one prepared statement and binds parameters, then executes within a loop. This provides stable/secure insert queries and avoids making so many escaping calls.
Code:
// switch procedural connection to object-oriented syntax
$stmt = $con->prepare('INSERT INTO maint_track (`vsr`,`ofice`,`date`,`type`,`qty`,`uprice`,`tprice`)
VALUES (?,?,?,?,?,?,?)'); // use ?s as placeholders to declare where the values will be inserted into the query
$stmt->bind_param("sssssss", $vsr, $ofice, $date, $type, $qty, $uprice, $tprice); // assign the value types and variable names to be used when looping
foreach ($_POST['vsr'] as $rowIndex => $vsr) {
/*
If you want to conditionally abort/disqualify a row...
if (true) {
continue;
}
*/
$ofice = $_POST['ofice'][$rowIndex];
$date = $_POST['date'][$rowIndex];
$type = $_POST['type'][$rowIndex];
$qty = $_POST['qty'][$rowIndex];
$uprice = $_POST['uprice'][$rowIndex];
$tprice = $_POST['tprice'][$rowIndex];
echo "<div>Row# {$rowIndex} " . ($stmt->execute() ? 'added' : 'failed') . "</div>";
}
To deny the insertion of a row, use the conditional continue that is commented in my snippet -- of course, write your logic where true is (anywhere before the execute call inside the loop will work).
To adjust submitted values, overwrite the iterated variables (e.g. $vsr, $ofice, etc) before the execute call.
If you'd like to enjoy greater data type specificity, you can replace s (string) with i (integer) or d (double/float) as required.