I just switched to PDO from mySQLi (from mySQL) and it's so far good and easy, especially regarding prepared statements
This is what I have for a select with prepared statement
Main DB file (included in all pages):
class DBi {
public static $conn;
// this I need to make the connection "global"
}
try {
DBi::$conn = new PDO("mysql:host=$dbhost;dbname=$dbname;charset=utf8", $dbuname, $dbpass);
DBi::$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
DBi::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo '<p class="error">Database error!</p>';
}
And in my page:
try {
$sql = 'SELECT pagetitle, pagecontent FROM mypages WHERE pageid = ? LIMIT 1';
$STH = DBi::$conn->prepare($sql);
$STH->execute(array($thispageid)); // $thispageid is from a GET var
}
catch(PDOException $e) {
echo '<p class="error">Database query error!</p>';
}
if ($STH) { // does this really need an if clause for it self?
$row = $STH->fetch();
if (!empty($row)) { // was there found a row with content?
echo '<h1>'.$row['pagetitle'].'</h1>
<p>'.$row['pagecontent'].'</p>';
}
}
It all works. But am I doing it right? Or can I make it more simple some places?
Is using if (!empty($row)) {} an ok solution to check if there was a result row with content? Can't find other decent way to check for numrows on a prepared narrowed select
catch(PDOException $e) {
echo '<p class="error">Database query error!</p>';
}
I would use the opportunity to log which database query error occurred.
See example here: http://php.net/manual/en/pdostatement.errorinfo.php
Also if you catch an error, you should probably return from the function or the script.
if ($STH) { // does this really need an if clause for it self?
If $STH isn't valid, then it should have generated an exception and been caught previously. And if you had returned from the function in that catch block, then you wouldn't get to this point in the code, so there's no need to test $STH for being non-null again. Just start fetching from it.
$row = $STH->fetch();
if (!empty($row)) { // was there found a row with content?
I would write it this way:
$found_one = false;
while ($row = $STH->fetch()) {
$found_one = true;
. . . do other stuff with data . . .
}
if (!$found_one) {
echo "Sorry! Nothing found. Here's some default info:";
. . . output default info here . . .
}
No need to test if it's empty, because if it were, the loop would exit.
Related
when executing the form, the data is not inserting. I have activated SQLITE3 and I am not skipping any type of error.
The echo of the try is to see what was wrong but nothing. I see everything right.
Does anyone help me?
$username = $_POST['nombre'];
$clave = $_POST['clave'];
$apenom = $_POST['apenom'];
try {
$bd = new SQLite3("test");
//preparamos la sentencia
echo "INSERT INTO usuarios (username,clave,apenom) VALUES ('$username','$clave','$apenom')";
$bd->exec("INSERT INTO usuarios (username,clave,apenom) VALUES ('$username','$clave','$apenom')");
/* while ($row = $resultado->fetchArray()) {
echo "{$row['username']} {$row['clave']} {$row['apenom']} \n";
} */
} catch (\Throwable $th) {
echo $th;
}
Do take the advice from the comments into account, database security is not something you should 'wing'...
As for a little help on setting up a connection and importantly debugging if anything goes wrong so you know what to fix, the following 'skeleton' might help:
<?php
try {
// connect to your database
$sqlite = new SQLite3('test.db');
}
catch (Exception $e) {
// if no connection could be established a exception is thrown
echo $e->getMessage();
}
// your query
$query = '...';
$result = $sqlite->query($query); // result object (FALSE on error)
if (!$result) {
// query failed for some reason...
echo $sqlite->lastErrorMsg();
} else {
// do something with result
}
I am trying to get a mysql data from the table, here -
try
{
$stmt = $user->prepare("SELECT status FROM users");
$result=$stmt->fetch(PDO::FETCH_ASSOC);
if($result['status'] != "Y")
{
$error[] = "Some error warning!";
}
else
{
// Some php codes
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
Here user is a class where prepare is db connection mysql prepare function. The error always prints - "Array!". I am new to php. Any help will be appreciated.
EDIT: I have managed to solve the problem.
You forgot the call of PDOStatement::execute(). See php.net for some examples.
Have you already tried this?
try
{
$stmt = $user->prepare("SELECT status FROM users");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if($result['status'] != "Y")
{
$error[] = "Some error warning!";
}
else
{
// Some php codes
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
Regarding the Array! output: Did you post the whole code of your script? Were do you try to print the array $error?
I have 2 DBs: 1 in MySQL and the other one on SQLite3.
I need to insert the same data into both. To achieve this by a Form, I'm making a PHP script, that has some issue.
Here below the code then the explanation on what's going on:
// MySQL
try {
$sql = new PDO($pdo_servername, $username, $password, $pdo_options);
$sql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$ret = $sql->exec($query);
if(!$ret){
echo $sql->lastErrorMsg();
} else {
echo "New record created successfully on MySQL DB";
}
} catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$sql->close();
// SQLite
try {
$sqlite = new PDO($pdo_servername_sqlite3);
$sqlite->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$retlite = $sqlite->exec($query);
if(!$retlite){
echo $sqlite->lastErrorMsg();
} else {
echo "New record created successfully on SQLite3 DB";
}
} catch (PDOException $e) {
echo $sqlite . "<br>" . $e->getMessage();
}
$sqlite->close();
The MySQL works fine, while the SQLite3 doesn't even start.
Inverting the blocks, thus first SQLite3 then MySQL, the issue is inverted: the SQLite3 works fine and MySQL doesn't start.
I have not any error returned
I tried also to avoid any try-catch-finally, and I just wrote the code as simple it is, and I got the same identical situation.
Is it forbidden to open 2 PDO connections, to 2 different DBs?
Where is my mistake please?
Try this way, that is the only breakpoint where you really need try...catch:
// MySQL
try {
$sql = new PDO($pdo_servername, $username, $password, $pdo_options);
} catch (PDOException $e) {
echo 'MySQL connection failed: ' . "<br>" . $e->getMessage();
$sql = false;
}
// SQLite
try {
$sqlite = new PDO($pdo_servername_sqlite3);
} catch (PDOException $e) {
echo 'SQLite connection failed: '. "<br>" . $e->getMessage();
$sqlite = false;
}
if ($sql != false) {
$ret = $sql->exec($query);
if(!$ret){
echo $sql->lastErrorMsg();
} else {
echo "New record created successfully on MySQL DB";
}
$sql->close();
}
if ($sqlite != false) {
$retlite = $sqlite->exec($query);
if(!$retlite){
echo $sqlite->lastErrorMsg();
} else {
echo "New record created successfully on SQLite3 DB";
}
$sqlite->close();
}
First of all I want to thank everybody contributed here :)
I would like to post the definitive working code, because some line, should also be changed, respect the above code.
Indeed the PDO method lastErrorMsg(); seems don't exist, and the same for the PDO method close(); It should be used errorInfo()in place of lastErrorMsg();and it's an array. While to close the DB connection: I read somewhere here on Stackoverflow that when the script execution ends, automatically PDO closes it, OR you need to destroy the object assign a null.
Because finally the code suggested by #Alex, with these small changes, was working, I was able to get the errors from PHP highlighting the above details.
Please here below the final working code, hoping that can be useful to any other had my same issue:
/**
* MySQL - try to open it. If it fails,
* it returns which error and continues the execution of the script
*/
try {
$sql = new PDO($pdo_servername, $username, $password, $pdo_options);
} catch (PDOException $e) {
echo 'MySQL connection failed: ' . "<br>" . $e->getMessage();
$sql = false;
}
/**
* SQLite - try to open it. If it fails,
* it returns which error and continues the execution of the script
*/
try {
$sqlite = new PDO($pdo_servername_sqlite3);
} catch (PDOException $e) {
echo 'SQLite connection failed: '. "<br>" . $e->getMessage();
$sqlite = false;
}
/**
* If the connection is made, it executes the Query
* If anything wrong with the Query insertion, an error is returned.
* The script continues
*/
if ($sql != false) {
$ret = $sql->exec($query);
if(!$ret){
print_r($sql->errorInfo()); // THIS is the valid method for PDO Exec and returns an array
} else {
echo "New record created successfully on MySQL DB";
}
}
if ($sqlite != false) {
$retlite = $sqlite->exec($query);
if(!$retlite){
print_r($sqlite->errorInfo()); // THIS is the valid method for PDO Exec and returns an array
} else {
echo "New record created successfully on SQLite3 DB";
}
}
/**
* Closes the DB Connections
*/
$sql = null;
$sqlite = null;
Thanks to all of you for your valid help. I very much appreciated it :)
Database connecting is working. The SELECT AND UPDATE FUNCTION in the class is not working at all.It is not even showing errors to help me sort out the problem. I am trying to learn how to use the prepare ,bind-param and execute statement. Please can someone help look at the codes and advise what may be wrong with it. Just spent loads of hours on this and just cant figure where the problems is. please can some help me.I am a novice and writing my very first codes . Many thanks in advance
<?php class connect_dbase{
public $mysqli;
public function connection($host="localhost",$user="root",$password="london",$db_name="users")
{
$this->mysqli=new mysqli($host,$user,$password,$db_name);
if ($this->mysqli->connect_error) {
die('Connect Error: ' . $this->mysqli->connect_error);
}
else{
echo " Database connection successful";
}
}
public function display_all($id){
if($stmt = $this->mysqli->prepare("SELECT * FROM user WHERE id =?")){
/* bind parameters for markers */
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
if($stmt->num_row() >0){
echo 'Total results: ' . $resultrol->num_rows;
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
echo $row['email'];
echo $row['address'];}
}
else { echo "no result found";}
}
else
{
echo "cant prepare result";
}
}
public function update_post($name, $address,$email,$mob,$id)
{
$up="UPDATE user SET name=?, address =?,email=?,mobile=? WHERE id =?";
if($stmt=$mysqli->prepare($up))
{
$stmt->bind_param("sssii", $name, $address,$email,$mob,$id);
if($stmt->excute()) {
echo " post updated";
header('location:index.php');
}
else
{
echo "post not executed";
}
}else{ echo " cannot prepare statement";}
}
}
$connect_dbase=new connect_dbase();
$connect_dbase->connection();
$connect_dbase->display_all(2);
$connect_dbase-> update_post("john","kkkkk","kkk#yahoo.com",98765,2);
// These 2 functions- $connect_dbase->display_all(2); and
$connect_dbase-> update_post("john","kkkkk","kkk#yahoo.com",98765,2); are not working when called from the class above .
?>
I agree with #MikeBrant's comments. You should make the connection happen in the constructor if you want to be assured that the connection is successful before you try to call it.
Here's another tip:
if($stmt->num_row() >0){
Note that num_rows() doesn't return anything useful until after the client has fetched the rows. So calling it right after execute() is pretty much guaranteed to make it return the wrong number.
You need to use mysqli::store_result() to transfer the result set from the server to the client, and then num_rows() will work. But be careful if the result set is very large, it could use too much memory.
Taking into account the input from Mike and Bill I have modified your code to make it functional. It could use some more work but it should give you a starting point at the very least. I created a test database with three fields, id, name and email but you should be able to plug in your own database and fields and have it still work.
<?php
class connect_dbase {
public $mysqli;
public function connection($host="localhost",$user="root",$password="",$db_name="test")
{
$this->mysqli=new mysqli($host,$user,$password,$db_name);
if ($this->mysqli->connect_error) {
die('Connect Error: ' . $this->mysqli->connect_error);
} else {
// return a true value here if successful, that way you can check
// if your connection was established
return true;
}
}
public function display_all($id){
if($stmt = $this->mysqli->prepare("SELECT * FROM test WHERE id =?")) {
// some minor changes to the bind and execute statments. I
// wrapped them in an if just to make sure there were no errors
// if i had more time i might make these more elegant rather than just
// echoing them out
/* bind parameters for markers */
if(!($stmt->bind_param('i',$id))) {
echo $stmt->error;
}
/* execute query */
if(!($stmt->execute())) {
echo $stmt->error;
}
// You could also bind the results to specific variables here and return those
//$stmt->bind_result($id,$name,$email);
//$stmt->fetch();
//$result = $name;
//assign the results to a variable and then return that variable
//rather than processing the results here
$result = $stmt->get_result();
return $result;
} else {
// if an error occurs return the error, once again another place for
// improvement but at the very least will show you an error
echo $this->mysqli->error;
}
}
public function update_post($name, $email, $id)
{
$up="UPDATE test SET name=?, email=? WHERE id =?";
// originally had $mysqli->prepare($up), fixed syntax
if($stmt = $this->mysqli->prepare($up))
{
//$stmt->bind_param("sssii", $name, $address,$email,$mob,$id);
$stmt->bind_param("ssi", $name, $email,$id);
// execute was spelled wrong
if($stmt->execute()) {
return true;
} else {
return $stmt->error;
//return false;
}
} else {
return false;
}
}
}
// set up database connection
$connect_dbase = new connect_dbase();
if($connect_dbase->connection()) {
// if connection was successful, call display_all
// and assign the results to $result
$result = $connect_dbase->display_all(2);
// you could do a foreach here also but since there
// was only one result i just echoed the values
while($row = $result->fetch_array()) {
echo $row['id'] . "<br/>";
echo $row['name'] . "<br/>";
echo $row['email'] . "<br/>";
}
// then call update_post
$update_result = $connect_dbase->update_post("asdf","asdf#yahoo.com",2);
// show a message if the update_post was successful
if($update_result) {
echo "Update successful";
}
}
?>
I commented the areas I switched around so you have an idea of what I did.
Ok, I have a database full of values with one field value for prospects and another for clients...
I'd like to retrieve only the clients information...
How do I write the function???
UPDATE
Here is the script I tried to write:
<?php
try {
$sql = "SELECT * FROM clients" // WHERE history" or die(mysql_error());
foreach ($dbh->query($sql) as $row) {
$row['history'] = $value;
if ($value == 'clients'){
echo "1212";
} else {
echo "Failed";
return;
}
}
$dbh = null;
} catch (PDOException $e) {
echo "Failed: " . $e->getMessage();
$dbh->rollback();
}
?>
There's no reason to do a rollback here, especially since you haven't started a transaction, and this is just a SELECT, so there's nothing to rollback ... I'm also not sure why you're nulling out $dbh. It's possible to reuse $dbh for other queries, or throughout your application...
Also, your select statement should reflect what data you actually need. If all you need is history, then SELECT history FROM clients[...] is best.
<?php
try {
$sql = "SELECT * FROM clients WHERE history = 'clients'";
$query = $dbh->prepare($sql);
$query->execute();
while($row = $query->fetch())
{
if($row['history'] == 'clients'){
echo '1212';
}
}
} catch (PDOException $e) {
echo "Failed: " . $e->getMessage();
}
?>
Based on your sample script this would do the same but it would place the conditional operator in the query at the database layer instead of within the script at the application layer:
<?php
try {
$sql = "SELECT * FROM clients WHERE history = 'clients'" // WHERE history" or die(mysql_error());
foreach ($dbh->query($sql) as $row) {
echo "1212";
}
$dbh = null;
} catch (PDOException $e) {
echo "Failed: " . $e->getMessage();
$dbh->rollback();
}
?>
Of course, it obviously won't reflect non-client rows like your sample did, but from what I could understand of your question this was what you actually wanted to have happen.