PHP Get JSON & Insert Into DB Via PDO [duplicate] - mysql

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 5 years ago.
My PHP Code:
<?php
$host = ""; $db_name = ""; $username = ""; $password = "";
try {
$conn = new PDO("mysql:host=".$host.";dbname=".$db_name, $username, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$json = file_get_contents('');
$obj = json_decode($json, TRUE);
$stmt = $conn->prepare("INSERT INTO item_details (item_id,value,circulation) VALUES (:item_id,:value,:circulation");
foreach($obj['items'] as $key => $index) {
$item_id = $key;
$value = $index['value'];
$circulation = $index['circulation'];
$stmt->bindparam(":item_id", $item_id);
$stmt->bindparam(":value", $value);
$stmt->bindparam(":circulation", $circulation);
$stmt->execute();
}
?>
Problem:
I've tested via echoing the data to the page within my loop and the data is being retrieved, however no information is being submitted to my database.
Questions:
How can I improve upon my script to add relevant debugging lines to
find the cause?
Is it obvious why my script does not work? If so, could you please explain this however my above question will aid my learning curve with future development!

Catalin Minovici is correct about bindParam however PDO errors are not always thrown exceptions that can be caught, so a try/catch is only helpful here if you are going to check the PDO errors, and throw your own exception.
You have missed a parenthesis in your query preparation.
// missing paren...........................................................................................here: v
$stmt = $conn->prepare("INSERT INTO item_details (item_id,value,circulation) VALUES (:item_id,:value,:circulation)");
See the documentation for reading PDO query errors after your execute() on php.net
Additionally it is better to combine all of the results into a single insert operation, rather than executing a new insert on each iteration of the loop.

You forgot closing bracket in values:
prepare("INSERT INTO item_details (item_id,value,circulation) VALUES (:item_id,:value,:circulation)");

Related

Call to undefined method PDO::last_Insert_Id() [duplicate]

This question already has answers here:
PDO get the last ID inserted
(3 answers)
Closed 2 years ago.
I'm getting an error message: Call to undefined method PDO::last_Insert_Id()
Here's my code:
$testcode = $conn -> prepare("INSERT INTO tblCategory
(Category, DisplayOrder)
VALUES('Test', 0)");
try {
$testcode ->execute();
$ID = $conn->last_Insert_Id();
}
catch (PDOException $e)
{echo $e->getMessage();
}
var_dump($conn instance of PDO) returns bool(true) so $conn is the PDO connection.
How do I correct so I don't get the error? I do need that last inserted id. Thanks.
This PDO method is called lastInsertId(), not last_Insert_Id().
So:
$ID = $conn->lastInsertId();

What's the best way to fetch an array

Alright, so I believe that there is a better way that I can fetch an array from the database, here's the code right now that I have.
$id = 1;
$userquery = mysql_query("SELECT * FROM login WHERE id='$id'");
while($row = mysql_fetch_array($userquery, MYSQL_ASSOC)) {
$username = $row['username'];
$password = $row['password'];
$email = $row['email'];
}
So If I am not wrong, you want a better way to get all the returned rows from mysql in a single statement, instead of using the while loop.
If thats the case, then I must say mysql_ drivers do not provide any such functionality, which means that you have to manually loop through them using foreach or while.
BUT, since mysql_ is already depricated, you are in luck! you can actually switch to a much better and newer mysqli_ or the PDO drivers, both of which DO actually have functions to get all the returned rows.
For mysqli_: mysqli_result::fetch_all
For PDO : PDOStatement::fetchAll
Eg.
mysqli_fetch_all($result,MYSQLI_ASSOC);
// The second argument defines what type of array should be produced
// by the function. `MYSQLI_ASSOC`,`MYSQLI_NUM`,`MYSQLI_BOTH`.
Like the comments already told you: PHP's mysql driver is deprecated. And you should use prepared statements and parameters.
for example in PDO your code would look something like this:
//connection string:
$pdo= new PDO('mysql:host=localhost;dbname=my_db', 'my_user', 'my_password');
//don't emulate prepares, we want "real" ones:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
//use exception-mode if you want to use exception-handling:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$id = 1;
//it's always better to strictly use backticks for db-names (db, tables, fields):
$sql = "SELECT * FROM `login` WHERE `id` = :id";
try
{
//create your prepared statement:
$stmt = $pdo->prepare($sql);
//bind a parameter and explicitly use a parameter of the type integer (in this case):
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
//execute the query
$stmt->execute();
}
catch(PDOException $e)
{
exit("PDO Exception caught: " . $e->getMessage());
}
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$username = $row['username'];
$password = $row['password'];
$email = $row['email'];
}
here you go: your PHP-MySQL routine is save against SQL-injections now and no longer uses deprecated PHP-functions! it's kinda state of the art ;)

Using PDO_MYSQL DSN and Adding Attributes to the Array

I'm trying to create a secure, SQL-injection proof connection to a database using PDO. I've know certain character sets are vulnerable, but that UTF-8 is not one of them. I also know that I should turn PDO's prepared statement emulation mode off. Below is the code that I've put together for the connection. My question is twofold.
Can someone please take a look at my code below to make sure that I'm doing everything correctly? I've tested it, and it works. But is there something else I could add to make it more secure or am I doing it right?
I'm not 100% positive that my syntax for what's inside the array is correct, though I don't get any errors when I do an insert, so I'm inclined to believe that it is. However, is there a way to test or confirm that those attributes are actually being set? Or can someone tell by looking that the syntax is correct and those attributes are definitely being set?
Thanks for any help in advance. My full code for the database connection and an insert using a prepared statement is below.
function addItem($category, $item, $price) {
$dsn = 'mysql:host=localhost;dbname=myDatabase;charset=utf8';
$username = "myUsername";
$password = "myPassword";
$options = array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
try {
$link = new PDO($dsn, $username, $password, $options);
$query = $link->prepare("INSERT INTO items (category, item, price)
VALUES (:category, :item, :price)");
$query->bindParam(':category', $category);
$query->bindParam(':item', $item);
$query->bindParam(':price', $price);
$query->execute();
echo "New item added successfully";
}
catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
$link = null;
}

Admin panel - Creating an edit users button

I've created an admin panel on my website so when the admin logs in he can edit users. I'm trying to get it to create a table that displays a list of all the users on the database, however, when I run it I get the error:
No database selected
Here is the code in my editusers.php:
<?php
include 'adminpage.php';
include 'connection.php';
$sql = "SELECT * FROM Users";
$result = mysql_query($sql)or die(mysql_error());
echo "<table>";
echo "<tr><th>UserID</th><th>First Name</th><th>Last Name</th><th>Email</th><th>D-O-B</th></tr>Username</th><th>Password</th><th>";
while($row = mysql_fetch_array($result)){
$userid = $row['UserID'];
$firstname = $row['FirstName'];
$lastname = $row['LastName'];
$email = $row['Email'];
$dob = $row['DateofBirth'];
$username = $row['Username'];
$password = $row['Password'];
// Now for each looped row
echo "<tr><td style='width: 200px;'>".$userid."</td><td style='width: 200px;'>".$firstname."</td><td>".$scale."</td><td>".$lastname."</td><td>".$email."</td></tr>".$dob."</td></tr>".$username."</td></tr>".$password."</td></tr>";
} // End our while loop
echo "</table>"
?>
First of all it looks like you are using mysql which isn't a wise move. This is because Mysql is actually deprecated and was improved to mysqli. Your problem may be to do with your database connection. You also haven't set a database. Like I said you can set an active database in your connection script. It should or could look something like this.
<?php
$conn = mysqli_connect("localhost", "root", "password", "database");
// Evaluate the connection
if (mysqli_connect_errno()) {
echo mysqli_connect_error();
exit();
}
?>
After that, your sql query is correct by selecting all from you table 'users' but in order to proceed I recommend creating a query where you use mysqli_query an select the $sql and $conn as parameters. In all honesty it is much advised to stop and continue once you have adapted to mysqli. Alternatively you can use PDO which in some cases can be seen as better to use rather than mysqli but the choice is yours. I personally would get to grips with mysqli and then look at some answers on Stack Overflow to decide whether you should use PDO or not. Visit the PHP manual here. Enter all the mysql functions you know and it will show you how to use the new mysqli version of the functions. Don't think that it is as simple as just adding and 'i' to the end of a mysql function. That's what I initially thought but there is alot to do with extra parameters etc. Hope this helps :-)

Why am I getting error SQLSTATE[HY093]: Invalid parameter number: ? How can I fix it?

Based on this question How to insert array into mysql using PDO and bindParam?
I'm trying to insert values of an array into mysql via PDO.
I'm having a hard time of it, because I keep getting the following error.
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
for this line $stmt->execute();
I'm guessing the problem has something to do with this line
$stmt->bindParam(':val$count', $val,PDO::PARAM_STR); Specifically 'val$count', but I'm not sure exactly what is going wrong.
QUESTION: What am I doing wrong? How can I fix this?
Anyway here is the code I'm using along with the sample array.
$lastInsertValue=87;
$qid[0][0]=1;
$qid[0][1]=1;
$qid[1][0]=2;
$qid[1][1]="null";
$qid[2][0]=3;
$qid[2][1]=0;
$array_count = count($qid);
if (isset($lastInsertValue))
{
try
{
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$stqid=array();
$a=0;
for ($i=0; $i<$array_count; $i++)
{
$stqid[$a]=$lastInsertValue;
$a++;
$stqid[$a]=$qid[$i][0];
$a++;
$stqid[$a]=$qid[$i][1];
$a++;
}
$sql = "INSERT INTO qresults (instance, qid, result) VALUES ( :val0, :val1, :val2)";
$count = 0;
$stmt = $dbh->prepare($sql);
foreach ($stqid as $val)
{
$stmt->bindParam(':val$count', $val,PDO::PARAM_STR);
$count++;
}
$stmt->execute();
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
Yikes, so many issues.
Your array building is so verbose. Try this
$stqid = array();
foreach ($qid as $qidArr) {
$stqid[] = $lastInsertValue; // no idea why you repeat this
$stqid[] = $qidArr[0];
$stqid[] = $qidArr[1];
}
Use positional placeholders if you're simply relying on number of arguments
$sql = 'INSERT INTO ... VALUES (?, ?, ?)';
bindParam uses references which you are overwriting with each loop iteration. You would want to use bindValue() instead
Your query only has 3 placeholders but your $stqid array has 9 items. This is the source of your error.
You have single quotes around a variable, which will be treated as the variable name $count (not the value), try concatenating the variable to the string. Give this a try:
$stmt->bindParam(':val' . $count, $val,PDO::PARAM_STR);
for ($i=0; $i<$array_count; $i++)
{
$stqid[$a]=$lastInsertValue;
$a++;
$stqid[$a]=$qid[$i][0];
$a++;
$stqid[$a]=$qid[$i][1];
$a++;
}
so in case $i = 2, it will add $stqid[6], $stqid[7], $stqid[8] so
foreach ($stqid as $val)
{
$stmt->bindParam(':val$count', $val,PDO::PARAM_STR);
$count++;
}
will give you :val0 to :val8
In your query you have only :val0 to :val2.
Also having multiple values in one field in database is bad. Don't do it. Try to redesign your DB differently
EDIT: bad math in the morning... sorry