PHP: one PDO instance breaks transaction of other PDO instance - php

The code below works and although while having a running transaction I create another PDO object, this does not disturb my transaction:
$dsn = 'mysql:host=' . "localhost" . ';dbname=' . "somedb";
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_TO_STRING
);
// first PDO object
$db = new \PDO($dsn, "someuser", "somepass", $options);
$db->beginTransaction();
$stmt = $db->prepare("INSERT INTO vbclient set company = 'test'");
$stmt->execute();
// second PDO object
$dbnew = new \PDO($dsn, "someuser", "somepass", $options);
$newstmt = $dbnew->prepare('select * from vbclient where clientID = 1');
$newstmt->execute();
$stmt = $db->prepare("INSERT INTO vbclient set company = 'test2'");
$stmt->execute();
$db->commit();
But if I put the creation of the second PDO object into a seperate function it seems to kill the transaction of the first PDO object:
$dsn = 'mysql:host=' . "localhost" . ';dbname=' . "somedb";
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_TO_STRING
);
// first PDO object
$db = new \PDO($dsn, "someuser", "somepass", $options);
$db->beginTransaction();
$stmt = $db->prepare("INSERT INTO vbclient set company = 'test'");
$stmt->execute();
secondPDO();
$stmt = $db->prepare("INSERT INTO vbclient set company = 'test2'");
$stmt->execute();
$db->commit();
function secondPDO() {
$dsn = 'mysql:host=' . "localhost" . ';dbname=' . "somedb";
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_TO_STRING
);
// second PDO object
$dbnew = new \PDO($dsn, "someuser", "somepass", $options);
$newstmt = $dbnew->prepare('select * from vbclient where clientID = 1');
$newstmt->execute();
}
I get the error "There is no active transaction." I understand that this normally happens if I overwrite the PDO handle with another instance. But I don't do that and the error only occurs if the second PDO object is in another function.
Any ideas why this is?
Thanks.

Related

Why does the keys of PDO query() result contain tablename?

I connected mysql with PDO like this:
$servername = 'localhost';
$servername = 'localhost';
$dbname = 'atlas';
$table = 'homepage_pv';
$username = 'root';
$password = 'mysql';
$conn = null;
try {
$conn = new PDO(
"mysql:host=$servername;dbname=$dbname",
$username,
$password,
array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
)
);
}
catch(PDOException $e) {
echo "connect to mysql failed : " . $e->getMessage();
$conn = null;
exit;
}
$result = $conn->query('SELECT * from homepage_pv')->fetchAll(PDO::FETCH_NAMED);
echo "result=" . json_encode($result);
the result is :
result=[{"homepage_pv.id":"1","homepage_pv.datetime":"2019-08-19 22:56:26"},{"homepage_pv.id":"2","homepage_pv.datetime":"2019-08-19 22:56:28"},{"homepage_pv.id":"3","homepage_pv.datetime":"2019-08-19 23:01:58"}]
The keys contain the table name "homepage_pv" , which is not expected;
But where I create PDO like this :
try {
$conn = new PDO(
"mysql:host=$servername;",
...
);
}
...
$result = $conn->query('SELECT * from atlas.homepage_pv')->fetchAll(PDO::FETCH_NAMED);
echo "result=" . json_encode($result);
the keys in the result do not contain tablename any more, like this:
result=[{"id":"1","datetime":"2019-08-19 22:56:26"},{"id":"2","datetime":"2019-08-19 22:56:28"},{"id":"3","datetime":"2019-08-19 23:01:58"},{"id":"4","datetime":"2019-08-19 23:08:48"}]
In case1 , I specified dbname when creating PDO and leaved out it when doing query;
In case2 , it's is on the contrary;
So what cause it? how can I specify dbname when creating PDO without the keys in result containing tablename?
Use PDO::FETCH_ASSOC in fetchAll(). If you use PDO::FETCH_NAMED it will return with alias name. If alias not present then with the table name. Attaching the doc for your further reference.

Problem converting mysqli to PDO | PHP mySQL

I am currently converting my mySQLi PHP code into PDO for better security and I am having some trouble understanding how I can convert the code below and implement it into my new PDO PHP
The code below should take the last inserted ID (the one the PDO is inserting) and set the column idnum equal to the NUM(and the last inserted id).
How can this be converted and added to the PDO?
if (mysqli_query($conn, $sql)) {
$last_id = mysqli_insert_id($conn);
$sql = "UPDATE Equipment SET idnum = CONCAT('NUM', '$last_id') WHERE equipment_id = '$last_id'";
mysqli_query($conn, $sql);
echo "New record created successfully. Last inserted ID is: " . last_id;
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
I would like to add the code to the following PDO PHP script:
$hostdb = 'localhost';
$namedb = 'dbname';
$userdb = 'userdb';
$passdb = 'passdb';
$charset = 'utf8';
if (isset($_POST['name'], $_POST['place'], $_POST['person'] , $_POST['number'] , $_POST['other_name'])) {
// Connect and create the PDO object
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
];
$conn = new PDO("mysql:host=$hostdb;dbname=$namedb;charset=$charset", $userdb, $passdb, $options);
$stmt = $conn->prepare( ' INSERT INTO `Table1` (name, place, person, number, other_name, progress)
VALUES (:name,:place,:person,:number,:other_name, "Done") ' );
$stmt->execute([
'name' => $_POST['name'],
'place' => $_POST['place'],
'person' => $_POST['person'],
'number' => $_POST['number'],
'other_name' => $_POST['other_name'],
]);
// Shows the number of affected rows
echo 'Affected rows : '. $stmt->rowCount();
}
Like this I guess (if you want them combined):
$hostdb = 'localhost';
$namedb = 'dbname';
$userdb = 'userdb';
$passdb = 'passdb';
$charset = 'utf8';
if (isset($_POST['name'], $_POST['place'], $_POST['person'] , $_POST['number'] , $_POST['other_name'] )) {
// Connect and create the PDO object
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
];
$conn = new PDO("mysql:host=$hostdb;dbname=$namedb;charset=$charset", $userdb, $passdb, $options);
try{
//start a transaction {ACID}
$conn->beginTransaction();
$stmt = $conn->prepare('INSERT INTO `Table1` (`name`, `place`, `person`, `number`, `other_name`, `progress`)
VALUES (:name,:place,:person,:number,:other_name, "Done") ' );
$stmt->execute([
'name' => $_POST['name'],
'place' => $_POST['place'],
'person' => $_POST['person'],
'number' => $_POST['number'],
'other_name' => $_POST['other_name'],
]);
//get the last insert ID
$last_id = $conn->lastInsertId();
$stmt = $conn->prepare('UPDATE `Equipment` SET `idnum` = CONCAT("NUM", :last_id_0) WHERE `equipment_id` = :last_id_1');
//named placeholders must be unique
$stmt->execute([
'last_id_0' => $last_id,
'last_id_1' => $last_id
]);
echo "New record created successfully. Last inserted ID is: " . $last_id;
//commit the changes
$conn->commit();
}catch(PDOException $e){
//roll back the changes on errors
$conn->rollback();
echo $e->getMessage();
}
// Shows the number of affected rows this is pointless (for insert 1 row it's always 1 or an error)
//echo 'Affected rows : '. $stmt->rowCount();
}
Transactions are like changing the DB for pretend (if it's INNODB table), then if there is an error with one of the query both fail.
It's advisable to use them when creating related records that way you don't leave orphan records or rows without the relationship just hanging around.

sqlite to mysql using php

I have an application that writes it's data to SQLite everyday. I now want to upload this data into my webhost to use. So I have a scheduled sFTP script to upload the .sqlite file to my webhost and then run another scheduled task to run the php code.
I know that I can use SQLite with PDO but all my other data on the host is in MySQL, so I want to keep everything in the MySQL format.
I have tried writing some php code that will read the sqlite file via PDO and then insert into the MySQL table again with PDO. The script will hopefully run on multiple tables to import so using foreach with Key/Values so I do not have to hardcode every single column in each table (about 30 columns per table)
However I have tried various things but just can not seem to find why the above code does not work problem so asking for help from much better minded users. Please view my code.
Thanks
<?php
ini_set('max_execution_time', 480); //480 seconds = 8 minutes
try {
// Connect to MySQL database
$host = '127.0.0.1';
$db = 'coredb';
$user = 'root';
$pass = 'password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdomysql = new PDO($dsn, $user, $pass, $opt);
// Connect to SQLite database in file
$file_db = new PDO('sqlite:frp.sqlite');
$file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'SELECT * from frp_teamdata';
$stmt = $file_db->prepare($sql);
$stmt->execute();
$sqliteresults = $stmt->fetch(PDO::FETCH_ASSOC);
foreach($sqliteresults as $results){
foreach($results as $key => $value){
$stmt = $pdomysql ->prepare("INSERT INTO frp_teamdata (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $key);
$stmt->bindParam(':value', $value);
$stmt->execute();
}
}
}
catch (PDOException $e) {
print 'Exception : ' . $e->getMessage();
}
?>
Give this a try:
<?php
ini_set('max_execution_time', 480); //480 seconds = 8 minutes
try {
// Connect to MySQL database
$host = '127.0.0.1';
$db = 'coredb';
$user = 'root';
$pass = 'password';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdomysql = new PDO($dsn, $user, $pass, $opt);
// Connect to SQLite database in file
$file_db = new PDO('sqlite:frp.sqlite');
$file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'SELECT * from frp_teamdata';
$stmt = $file_db->prepare($sql);
$stmt->execute();
$sqliteresults = $stmt->fetch(PDO::FETCH_ASSOC);
//Prepare the statement only once!
$stmtmysql = $pdomysql ->prepare("INSERT INTO frp_teamdata (name, value) VALUES (:name, :value)");
//Bind the params only once -- I assume the keys and values are strings
$stmtmysql->bindParam(':name', $key, PDO::PARAM_STR);
$stmtmysql->bindParam(':value', $value, PDO::PARAM_STR);
foreach($sqliteresults as $results){
foreach($results as $key => $value){
$stmtmysql->execute();
}
}
}
catch (PDOException $e) {
print 'Exception : ' . $e->getMessage();
}
?>
Note: I have not tried the code, so let me know if you have any issues.

insert slected data as Foreign key and SQLSTATE[23000]: Integrity constraint violation: 1048

Thank you for being here!
i want to be able to select acc_id from account_info table and insert it in patient_info table as Foreign Key
I am getting this error :
In my localhost i can see the value it's suppose to return.
And this error which I suppose it occurs because i haven't inserted acc_id yet SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'acc_id' cannot be null
Also var_dump($data) returns array(1) { [0]=> object(stdClass)#3 (1) { ["acc_id"]=> int(124) } }
php file :
<?php
header('Access-Control-Allow-Origin: *');
// Define database connection parameters
$hn = 'localhost';
$un = 'root';
$pwd = '';
$db = 'ringabell';
$cs = 'utf8';
// Set up the PDO parameters
$dsn = "mysql:host=" . $hn . ";port=3306;dbname=" . $db . ";charset=" . $cs;
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_EMULATE_PREPARES => false,
);
// Create a PDO instance (connect to the database)
$pdo = new PDO($dsn, $un, $pwd, $opt);
// Retrieve specific parameter from supplied URL
$data = array();
try{
$stmt = $pdo->query('SELECT acc_id FROM account_info ORDER BY acc_id DESC LIMIT 1');
$data = $stmt->fetchAll(PDO::FETCH_OBJ);
// Return data as JSON
echo json_encode($data);
var_dump($data);
$sql= "INSERT INTO patient_info(acc_id, p_fname, p_lname, p_gender, p_condition, p_birthdate, p_emergencycontact)
VALUES(:data, :p_fname, :p_lname, :p_gender, :p_condition, :p_birthdate, :p_emergencycontact)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':p_fname', $p_fname, PDO::PARAM_STR);
$stmt->bindParam(':p_lname', $p_lname, PDO::PARAM_STR);
$stmt->bindParam(':p_gender', $p_gender, PDO::PARAM_STR);
$stmt->bindParam(':p_condition', $p_condition, PDO::PARAM_STR);
$stmt->bindParam(':p_birthdate', $p_birthdate, PDO::PARAM_STR);
$stmt->bindParam(':p_emergencycontact', $p_emergencycontact, PDO::PARAM_STR);
$stmt->bindParam(':data', $acc_id, PDO::PARAM_STR);
$stmt->execute();
echo json_encode(array('message' => 'Congratulations the record was added to the database'));
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
It seems there are multiple issues in your code or the way you are trying to do things. Please check the code below. It should work. I have added few inline comments. Please check them:
<?php
// Define database connection parameters
$hn = 'localhost';
$un = 'root';
$pwd = '';
$db = 'ringabell';
$cs = 'utf8';
// Set up the PDO parameters
$dsn = "mysql:host=" . $hn . ";port=3306;dbname=" . $db . ";charset=" . $cs;
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_EMULATE_PREPARES => false,
);
// Create a PDO instance (connect to the database)
$pdo = new PDO($dsn, $un, $pwd, $opt);
// Retrieve specific parameter from supplied URL
$data = array();
try {
$stmt = $pdo->query('SELECT acc_id FROM account_info ORDER BY acc_id DESC LIMIT 1');
$data = $stmt->fetchAll(PDO::FETCH_OBJ);
// You do not need to return response from here
// echo json_encode($data);
// var_dump($data);
$sql= "INSERT INTO patient_info(acc_id, p_fname, p_lname, p_gender, p_condition, p_birthdate, p_emergencycontact)
VALUES(:acc_id, :p_fname, :p_lname, :p_gender, :p_condition, :p_birthdate, :p_emergencycontact)";
$stmt = $pdo->prepare($sql);
// the $p_fname, $p_lname, $p_gender etc variables in your code were never initiated. You would get
// notice for this if you had all error_reporting on. I am not sure from where you intend to get this info;
// so, I just added some dummy data.
$p_fname = 'Patient first name';
$p_lname = 'Patient last name';
$p_gender = 'm';
$p_condition = 'condition';
$p_birthdate = '1999-01-01';
$p_emergencycontact = 'Contact';
$stmt->bindParam(':p_fname', $p_fname, PDO::PARAM_STR);
$stmt->bindParam(':p_lname', $p_lname, PDO::PARAM_STR);
$stmt->bindParam(':p_gender', $p_gender, PDO::PARAM_STR);
$stmt->bindParam(':p_condition', $p_condition, PDO::PARAM_STR);
$stmt->bindParam(':p_birthdate', $p_birthdate, PDO::PARAM_STR);
$stmt->bindParam(':p_emergencycontact', $p_emergencycontact, PDO::PARAM_STR);
// You do not have any $acc_id variable in your code. To get data from your fetch you need to do
// like this:
$stmt->bindParam(':acc_id', $data[0]->acc_id, PDO::PARAM_STR);
$stmt->execute();
header('Access-Control-Allow-Origin: *');
// If you want to get the acc_id in your client side through the AJAX call, combine both
// mesage and data in the same JSON object.
echo json_encode(
array(
'message' => 'Congratulations the record was added to the database'
'data' => $data
)
);
} catch(PDOException $e) {
// make sure to send the proper status code
http_response_code(500);
// even error should be sent back as in json so that your javascript client can
// easily parse it
echo json_encode(
array(
'error' => $e->getMessage()
)
);
}
?>

PDO - 3D000 No database selected

I wanted to create a PDO mysql connection. But the execute() function returns false and the errorInfo() returns "No database selected!". But I selected a database.
This is my code:
$array = array("db" => "blogscript", "host" => "localhost", "user" => "root", "pass" => "");
$db = new PDO('mysql:dbname=' . $array['db'] . ';host=' . $array['host'] . '', $array['user'], $array['pass']);
$statement = $db->prepare('
SELECT *
FROM pages
');
$r = $statement->execute();
if ($r === false) {
return $statement->errorInfo();
}
The database "blogscript" existst.
Hard coding the connection with database & host in this order
$db = new PDO('dbname=blogscrip;mysql:host=localhost', root, pass);
Throws exception could not find driver
in the order in documentation
$dbh = new PDO('mysql:host=localhost;dbname=blogscript', root, pass);
Works
Change the order to host & database

Categories