Mysterious behaviour of php - php

Below code works as expected. It adds 3 entries to the table 'keywords'.
<?php
include "config.php";
try{
// $conn = new PDO(DBINFO,USER,PASS);
// $sql = "INSERT INTO projects (title,duration, startyear, description, tags,email) VALUES (:title,:duration, :startyear, :description, :tags,:email)";
// $stmt = $conn->prepare($sql);
// $stmt->bindParam(':title', $_POST['title'],PDO::PARAM_STR);
// $stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
// $stmt->bindParam(':duration', $_POST['duration'], PDO::PARAM_STR);
// $stmt->bindParam(':startyear', $_POST['startyear'], PDO::PARAM_STR);
// $stmt->bindParam(':description', $_POST['description'], PDO::PARAM_STR);
// $stmt->bindParam(':tags', $_POST['tags'], PDO::PARAM_STR);
// $stmt->execute();
for($i=0; $i<3; $i++){
$conn2 = new PDO(DBINFO,USER,PASS);
$sql2 = "INSERT INTO keywords (keyword,confidence) VALUES (:keyword,:confidence)";
$stmt2 = $conn2->prepare($sql2);
$a = 'asdfds';
$stmt2->bindParam(':keyword', $a,PDO::PARAM_STR);
$stmt2->bindParam(':confidence', $a, PDO::PARAM_STR);
$stmt2->execute();
}
}
catch(PDOException $pe){
die("Could not connect to the database :".$pe->getMessage());
}
?>
However, when I run the below code (where I uncommented the first part), the entries get added 6 times to the 'keywords' table.
<?php
include "config.php";
try{
$conn = new PDO(DBINFO,USER,PASS);
$sql = "INSERT INTO projects (title,duration, startyear, description, tags,email) VALUES (:title,:duration, :startyear, :description, :tags,:email)";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':title', $_POST['title'],PDO::PARAM_STR);
$stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
$stmt->bindParam(':duration', $_POST['duration'], PDO::PARAM_STR);
$stmt->bindParam(':startyear', $_POST['startyear'], PDO::PARAM_STR);
$stmt->bindParam(':description', $_POST['description'], PDO::PARAM_STR);
$stmt->bindParam(':tags', $_POST['tags'], PDO::PARAM_STR);
$stmt->execute();
for($i=0; $i<3; $i++){
$conn2 = new PDO(DBINFO,USER,PASS);
$sql2 = "INSERT INTO keywords (keyword,confidence) VALUES (:keyword,:confidence)";
$stmt2 = $conn2->prepare($sql2);
$a = 'asdfds';
$stmt2->bindParam(':keyword', $a,PDO::PARAM_STR);
$stmt2->bindParam(':confidence', $a, PDO::PARAM_STR);
$stmt2->execute();
}
}
catch(PDOException $pe){
die("Could not connect to the database :".$pe->getMessage());
}
?>
I can't understand this. Any help?

Why do you create 4 different connections to the same server and schema in the first place?
The loop creates connections and closes them automatically when the references to statements and connections are overwritten.
But the original connection from before the loop will stay open and is reused for the statements. If you create a third connection without closing it before the loop you'll end up with 9 entries.
So delete the references to connection objects if they are no longer needed (this includes associated statements).
Or better yet reuse connections instead of creating a new connection for every statement.

Related

Inserting Multiple Values with PDO and a Loop

To give you some background, the flow is: Connect to a 3rd party API, pull data stored as json, convert to php and use the data in the below code.
I found this work originally but unable to figure out how to modify it to my needs. Perhaps one of you could understand it better?
I am doing 3 things here. First checking the ID of a house + last_update stamp to determine which houses need to be updated in my database. If they exist but details have changed, drop the current data and store it in a variable ready to be inserted. If the data does not exist, insert it.
Something to note: The script takes so long to execute that I have to set set_time_limit(0); which I realise is bad practise but I needed to force the script to complete.
I have cut my code down quite a lot given that I had over 40 different manually entered prepared statements for either:
Updating records
Deleting records
Inserting records
I have identified the expected outputs using screenshots so please ignore any open braces at this point as the main issue is refining the code to a more dynamic approach and making it quicker of course.
<?php
$update = '';
$add = '';
if (!empty($houses)) {
foreach($houses as $travel_Prop) {
$Prop = $travel_Prop['data'][0]; // Need to check this!
if ($Prop['id'] > '0') { // Ignore empty arrays
$sql= "SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id";
$stmt = $extDb->prepare("$sql");
$stmt->bindParam(':travel_prop_id', $Prop['id'], PDO::PARAM_INT);
$stmt->execute();
$Result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($Result)) {
$travel_last_update = $Prop['last_update'];
$local_last_update = $Result[0]['last_update'];
if ($travel_last_update > $local_last_update) {
$update[] = $Prop;
echo 'Property ID: ' .$Prop['id'] .' Property modified: Updating Records.<br>';
} else {
echo 'Property ID: ' .$Prop['id'] .' Property details: Up to Date.<br>';
}
} else {
$add[] = $Prop;
echo 'Property ID: ' .$Prop['id'] .' Property Created: Adding to Records.';
}
}
}
NOTE: Code will carry on after screenshot output
# UPDATE
if (!empty($update)) {
//print_r($update);
foreach ($update as $PropUpdate) {
// Get all_prop_id
$sql= "SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id";
$stmt = $extDb->prepare("$sql");
$stmt->bindParam(':travel_prop_id', $PropUpdate['id'], PDO::PARAM_INT);
$stmt->execute();
//$Result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$obj = $stmt->fetchObject();
//echo $obj->filmName;
$all_prop_id = $obj->all_prop_id;
echo $all_prop_id;
// Update master db table a_property
$sql = "UPDATE travel_a_property SET last_update = :last_update
HERE all_prop_id = :all_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':last_update', $PropUpdate['last_update'], PDO::PARAM_STR);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->execute();
echo '<br>Prop Updated - all_prop_id : ' .$all_prop_id .'<br>';
# DELETe & INSERT
$sql = "DELETE FROM ot_b_address WHERE glob_prop_id = :glob_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':glob_prop_id', $glob_prop_id, PDO::PARAM_INT);
$stmt->execute();
$sql = "INSERT INTO ot_b_address(glob_prop_id, address1, address2, city, state, zip_code,
country, latitude, longitude) VALUES ( :glob_prop_id, :address1, :address2, :city, :state,
:zip_code, :country, :latitude, :longitude)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':glob_prop_id', $glob_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':address1', $PropUpdate['address']['address1'], PDO::PARAM_STR);
$stmt->bindParam(':address2', $PropUpdate['address']['address2'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropUpdate['address']['city'], PDO::PARAM_STR);
$stmt->bindParam(':state', $PropUpdate['address']['state'], PDO::PARAM_STR);
$stmt->bindParam(':zip_code', $PropUpdate['address']['zip_code'], PDO::PARAM_STR);
$stmt->bindParam(':country', $PropUpdate['address']['country'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropUpdate['address']['city'], PDO::PARAM_STR);
// use PARAM_STR although a number
$stmt->bindParam(':latitude', $PropUpdate['address']['latitude'], PDO::PARAM_STR);
$stmt->bindParam(':longitude', $PropUpdate['address']['longitude'], PDO::PARAM_STR);
$stmt->execute();
echo 'Address Updated <br>';
$sql = "DELETE FROM travel_d_urls WHERE all_prop_id = :all_prop_id";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->execute();
if (!empty($PropUpdate['urls'])) {
foreach($PropUpdate['urls'] as $row => $Url) {
$sql = "INSERT INTO travel_d_urls(all_prop_id, type, url)
VALUES ( :all_prop_id, :type, :url)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':type', $Url['type'], PDO::PARAM_STR);
$stmt->bindParam(':url', $Url['url'], PDO::PARAM_STR);
$stmt->execute();
echo 'URL '.$row .' Updated <br>';
}
}
}
} else {
echo 'no rates to Update <br>';
}
The output is pretty much just the same thing (whatever is being updated)
URL ADDED
URL ADDED
etc
The following code is the last if statement which tells the script to add the remaining properties if they do not exist.
} // end foreach $update
# INSERT ONLY
if (!empty($add)) {
foreach ($add as $PropAdd) {
$sql = "INSERT INTO travel_a_property(travel_prop_id, last_update)
VALUES ( :travel_prop_id, :last_update)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':travel_prop_id', $PropAdd['id'], PDO::PARAM_INT);
$stmt->bindParam(':last_update', $PropAdd['last_update'], PDO::PARAM_STR);
$stmt->execute();
$all_prop_id = $extDb->lastInsertId(); // Use this ID in all the following record inserts
echo '<br>Prop Added - all_prop_id : ' .$all_prop_id .'<br>';
##########################
$sql = "INSERT INTO travel_b_address(all_prop_id, address1, address2, city, state, zip_code, country,
latitude, longitude) VALUES ( :all_prop_id, :address1, :address2, :city, :state, :zip_code, :country,
:latitude, :longitude)";
$stmt = $extDb->prepare($sql);
$stmt->bindParam(':all_prop_id', $all_prop_id, PDO::PARAM_INT);
$stmt->bindParam(':address1', $PropAdd['address']['address1'], PDO::PARAM_STR);
$stmt->bindParam(':address2', $PropAdd['address']['address2'], PDO::PARAM_STR);
$stmt->bindParam(':city', $PropAdd['address']['city'], PDO::PARAM_STR);
$stmt->bindParam(':state', $PropAdd['address']['state'], PDO::PARAM_STR);
$stmt->bindParam(':zip_code', $PropAdd['address']['zip_code'], PDO::PARAM_STR);
$stmt->bindParam(':country', $PropAdd['address']['country'], PDO::PARAM_STR);
// use PARAM_STR although a number
$stmt->bindParam(':latitude', $PropAdd['address']['latitude'], PDO::PARAM_STR);
$stmt->bindParam(':longitude', $PropAdd['address']['longitude'], PDO::PARAM_STR);
$stmt->execute();
echo 'Address Added <br>';
} // end foreach
} // end !empty
$extDb = null;
}
?>
So to reiterate, the question here is not to identify what is wrong with my code as other than the speed, it is actually working fine. I would like to know if someone could identify the best way to make this dynamic to avoid having to tediously write the code 40 + times?
If anything is unclear, please let me know.
Cheers,
bench.
You are creating the prepared statements inside the foreach loop. Try to create the prepared statement outside of it. The idea of a prepared statement is that you prepare the statement once and execute it multiple times with different parameter values. This way the database only have to compile and optimize the SQL query once, which is more efficient than doing it foreach iteration.
if (!empty($houses)) {
$stmt = $extDb->prepare("SELECT * FROM travel_a_property WHERE travel_prop_id = :travel_prop_id");
//$stmt2 = ...
foreach ($houses as $travel_Prop) {
$prop = $travel_Prop['data'][0]; // Need to check this!
if ($prop['id'] > '0') { // Ignore empty arrays
if ($stmt->execute(array(':travel_prop_id' => $prop['id']))) {
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Do something with $result
}
}
//$stmt2->execute(...);
}
}

Trying to change it so that the system gets the date. Not to get the date from the user

I have an issue I am trying to get the current date when user updates the form. What I am trying to do is instead of posting what the user types in for the date. I wanted the system to get the date. How do I make it so that the update_process.php page gets the current date. In the $_POST[date] bindparam section. I tried adding getdate() in there but that does not work. I am confused on how to do it.
<?php
$serverName = "localhost";
try {
$db= new PDO( "sqlsrv:server=$serverName ; Database=systems_requests", "test", "test");
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
} catch(Exception $e) {
die( print_r( $e->getMessage() ) );
}
$sql = 'UPDATE requests SET id=:id, studentId= :studentId, name= :name, date= :date WHERE id= :id';
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $_POST['id'], PDO::PARAM_INT);
$stmt->bindParam(':studentId', $_POST['studentId'], PDO::PARAM_STR);
$stmt->bindParam(':name', $_POST['name'], PDO::PARAM_STR);
$stmt->bindParam(':date', $_POST['date'], PDO::PARAM_STR);
try {
$stmt->execute();
} catch(PDOException $exception) {
echo "Error: " . $exception->getMessage();
}
?>
also how would I change the count to reflect that to count how many Bob's signed up with todays date.
<?php
$stmt = $db->prepare("SELECT COUNT(*) AS rows_cnt FROM students WHERE name='Bob' AND date=getdate()");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['rows_cnt'];
}
?>
To fix my issue I had to remove set ID in order for the update to work.
$sql = 'UPDATE requests SET studentId= :studentId, name= :name, date=getdate() WHERE id= :id';
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $_POST['id'], PDO::PARAM_INT);
$stmt->bindParam(':studentId', $_POST['studentId'], PDO::PARAM_STR);
$stmt->bindParam(':name', $_POST['name'], PDO::PARAM_STR);
$stmt->execute();
$sql = 'UPDATE requests SET id=:id, studentId= :studentId, name= :name, date=getdate() WHERE id= :id';
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $_POST['id'], PDO::PARAM_INT);
$stmt->bindParam(':studentId', $_POST['studentId'], PDO::PARAM_STR);
$stmt->bindParam(':name', $_POST['name'], PDO::PARAM_STR);
$stmt->execute();
Like I said in the comments, I'm not sure what the role of $_POST['date'] is, so why are you using it? From your question, it seems like you just want the current date, not user input. In that case, you don't need to bind a parameter, you just put the date function in the query.

Converting MySql Insert To PDO

I am trying to convert this to PDO:
echo 'sup 1';
$sql = "INSERT INTO blogData(
title,
content,
category)
VALUES (
:title,
:content,
:category)";
echo 'sup 2';
$stmt = prepare($sql);
echo 'sup 3';
$stmt->bindParam(':title', $_POST['title'], PDO::PARAM_STR);
$stmt->bindParam(':content', $_POST['content'], PDO::PARAM_STR);
$stmt->bindParam(':category', 'City Secrets', PDO::PARAM_STR);
echo 'sup 4';
$stmt->execute();
echo 'sup 5';
header('location: http://www.backToThePageIPostedOn.com');
This is my current code but it is not entering to the DB:
$sql = "INSERT INTO blogData(
title,
content,
category)
VALUES (
:title,
:content,
:category)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':title', $_POST['title'], PDO::PARAM_STR);
$stmt->bindParam(':content', $_POST['content'], PDO::PARAM_STR);
$stmt->bindParam(':category', 'City Secrets', PDO::PARAM_STR);
$stmt->execute();
header('location: http://www.backToThePageIPostedOn.com');
Its stopping on the script page. This is my first time to use PDO so If someone could point out the error in my syntax I would appreciate it.
My code does not get past echo 'sup 2';
So I believe the error is in this line, $stmt = $pdo->prepare($sql);
I followed a tutorial to do this and I don't understand why they are adding the
$pdo in.
I was assuming thats supposed to be my connection but I have that set as
$con
When I change
$pdo to $con I still get the same cut off at echo 'sup 2';
Statement bindParam method accepts second parameter by reference. Only variables can be passed by reference.
The solution is to assign to variables the params you are going to bind:
$stmt = $pdo->prepare($sql);
$title = $_POST['title'];
$content = $_POST['content'];
$category = 'City Secrets';
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
$stmt->bindParam(':content', $content, PDO::PARAM_STR);
$stmt->bindParam(':category', $category, PDO::PARAM_STR);
$stmt->execute();
This is the correct working code for the question above.
$stmt->bindParam
changed to
$stmt->bindValue
And added the connection.php file for DB connection.
<?php
require_once( 'connection.php' );
$sql = "INSERT INTO blogData(
title,
content,
category)
VALUES (
:title,
:content,
:category)";
$stmt = $con->prepare($sql);
$stmt->bindParam(':title', $_POST['title'], PDO::PARAM_STR);
$stmt->bindParam(':content', $_POST['content'], PDO::PARAM_STR);
$stmt->bindValue(':category', 'City Secrets', PDO::PARAM_STR);
$stmt->execute();
header('location: http://www.website.com');
?>

Can you use more than one query with mysqli->prepare on one db connection?

I want to use a single database connection with multiple queries but use prepare and bind_param. How can i do this? I cant find it in the documentation.
Edit: i want two completely different queries.
$db = getConnection();
$query = "INSERT INTO talks(title, body, topic) VALUES(?, ?, ?)";
$stmt = $db->prepare($query);
$stmt->bind_param('sss', $title , $body, $topic);
$stmt->execute();
$stmt->close();
$query = "SELECT * WHERE title=?";
$stmt = $db->prepare($query);
$stmt->bind_param("s", $title);
$stmt->execute();
$stmt->bind_result($i, $t, $b, $to);
$stmt->fetch();
$id = $i;
$stmt->close();
Its telling me that $stmt isnt an object on the second go around
Just prepare a second query, as you did with the first.
$conn = new mysqli(....);
$stmt = $conn->prepare(....);
//Do stuff with $stmt
$stmt = $conn->prepare(...different...); //$stmt is overridden with the new query.
//Do stuff with the new $stmt.

pdo statement failing to execute

i have a pdo block for inserting values into my table as follows
try{
$user = 'root';
$pass = null;
$pdo = new PDO('mysql:host=localhost; dbname=divebay', $user, $pass);
$name = $_POST['name'];
$desc = $_POST['description'];
$cond = $_POST['condGroup'];
$sprice = $_POST['sprice'];
$iprice = $_POST['iprice'];
$incprice = $_POST['incprice'];
$duration = $_POST['duration'];
$img = $_POST['img'];
$owner = $_SESSION['username'];
$valid = "set";
$stmt2 = $pdo->prepare("SELECT * FROM auction WHERE ID = :id");
$stmt2->bindParam(":id", $random, PDO::PARAM_INT);
while(isset($valid)){
$random = rand(100000,999999);
$stmt2->execute();
if(!$stmt2->fetch(PDO::FETCH_ASSOC)){
unset($valid);
}
}
$timestamp = time() + ($duration * 24 * 60 * 60);
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description");
$stmt->bindParam(':id', $random, PDO::PARAM_INT);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':owner', $owner, PDO::PARAM_STR);
$stmt->bindParam(':holder', $owner, PDO::PARAM_STR);
$stmt->bindParam(':iprice', $iprice, PDO::PARAM_STR);
$stmt->bindParam(':sprice', $sprice, PDO::PARAM_STR);
$stmt->bindParam(':incprice', $incprice, PDO::PARAM_STR);
$stmt->bindParam(':etime', $timestamp, PDO::PARAM_INT);
$stmt->bindParam(':img', $img, PDO::PARAM_STR);
$stmt->bindParam(':condition', $condition, PDO::PARAM_STR);
$stmt->bindParam(':description', $description, PDO::PARAM_STR);
if($stmt->execute()){
$worked ="yes";
}
}catch(PDOException $e){
echo $e->getMessage();
}
i cant tell why this statement wont execute, the $worked variable has not been set when it is the script is run. all database column names and datatypes have been checked correct as they are. ive never had a problem with a statement not executing until now. whats wrong? how do i go about debugging this?
If you setup the database connection with error mode exception PDO will throw an exception if something is wrong with your statement. I also see that you are using the MySQL driver for PDO. If you do this you should always disable emulated prepared statements. So I would write you connection as following (note that I have also set the encoding):
$pdo = new PDO('mysql:host=localhost; dbname=divebay;charset=utf8', $user, $pass);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Also see this post for more information about this.
Once you have done this you will see that your statement is wrong. You have one missing ) at the end of the statement:
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description)");
^
Modify this line:
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description");
To
$stmt = $pdo->prepare("INSERT INTO auction(ID, name, owner, holder, sprice, iprice, incprice, etime, img, condition, description)
VALUES (:id, :name, :owner, :holder, :sprice, :iprice, :incprice:, :etime, :img, :condition, :description)");
The difference is the ) at the end.
And tell me if it works now.

Categories