I use this code for check connection to the database(MYSQL).If the database name not available then also it show connect successfully.
if(isset($_REQUEST['submit']))
{
echo $name = $_REQUEST['name'];
echo $pwd = $_REQUEST['password'];
$servername = "localhost";
$username = "root";
$password = "";
try
{
$conn = new PDO("mysql:host = $servername;dbname = pdo",$username,$password);
//echo "Connected successfully";
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "connect successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
}
TL;DR
Because your code is using try-catch blocks you can be sure that as long as no exceptions are thrown the connection was successfully established. Otherwise check the error code stored inside the exception to resolve the type of error.
More detailed
Your code makes use of exceptions, so if an error occurred while a connection was attempted established an exception would be thrown. As far as I know the PDO object throws exceptions by default while it is constructed and falls back to silent mode when to instance is created. So you are assured you will be warned if anything bad happens during construction.
Update 1
How to check the database name is available or not in to the database using PDO?
As said you can utilize exceptions. But instead of echoing the exception message you can inspect the returned error code using the PDOException method getCode(). Using php version 5.6.8 I will get the code 1049. You can then check using the following:
try {
$pdo = new PDO($dsn, $username, $passowrd, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]);
}catch(PDOException $exception) {
if($exception->getCode() == 1049) {
echo 'Database does not exist!';
}
// Continue error handling...
}
Update 2: Alternative
Using the same PHP version as above you can avoid selecting a database in the DSN. With this you can fetch a list of accessible databases for the used MYSQL user. Using this list you can check the existence of one or more databases at the same time and avoid the overhead of an exception halting execution of your script.
/*
* I assume you are on localhost.
*/
$pdo = new PDO('mysql:host=127.0.0.1', $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]);
$databases = $pdo->query('SHOW DATABASES'); // Does not require a prepared statement since it takes no input.
/*
* The following can be done more elegant/efficient.
*/
$exists = false; // Equals TRUE if the database exists.
$check = 'test'; // Enter the database to check for.
foreach($databases->fetchAll(PDO::FETCH_ASSOC) as list($database)) {
if($database == $check) {
$exists = true;
break;
}
}
Bonus
You are setting the error mode after the PDO instance has been constructed. This can also be done with the fourth parameter of PDO's constructer. I think this leads to more readable code.
I would also recommend setting the configuration PDO::ATTR_EMULATE_PREPARES to false. This ensure prepared statements are always used. The documentation can be found here.
$pdo = new PDO($dsn, $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]);
Happy coding!
Related
Recently, I switched to PDO and wanted to ask if is as safe as I do it or not?
(I filter the data before with much filter methods provided by php)
QUERY db:
include 'path_to_config_file_with_login_creds_for_db.php';
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
PDO::ATTR_PERSISTENT => false,
);
try {
$pdo = new PDO('mysql:host=' . $database_host . ';dbname=' . $database_name . ';charset=utf8mb4', $database_user, $database_pass, $options);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $exception) {
die("some error message");
}
try {
$statement = $pdo->prepare($sql);
$statement->execute($bindings);
$statement->closeCursor();
return $output;
} catch (PDOException $stmEx) {
die("again some error message");
}
UPDATE db:
include 'again_path_to_config_file_where_creds_to_db.php';
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
PDO::ATTR_PERSISTENT => false,
);
try {
$pdo = new PDO('mysql:host=' . $database_host . ';dbname=' . $database_name . ';charset=utf8mb4', $database_user, $database_pass, $options);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $exception) {
die("...");
}
try {
$statement = $pdo->prepare($sql);
$statement->execute($bindings);
$statement->closeCursor();
} catch (PDOException $stmEx) {
die("...");
}
Is this way safe or not?
It's all working fine but I want to know it its safe too
From the security point of view it should be safe as long as the query in $sql uses param binding properly. If the $sql variable is build like this then your code won't help you.
//DO NOT TRY THIS AT HOME
$sql = "SELECT * FROM `users` WHERE user='" . $_POST['user'] . "'";
But i can see several other issues with your code.
1) Your try ... catch blocks are useless. When you use PDO::ERRMODE_SILENT the PDO won't raise any exception. Only the $pdo->errorCode or $statement->errorCode properties will be set when error is encountered.
2) You are opening too many connections. I assume that you have the code you've shared in some function that you plan to call like queryDb($sql, $params); That means that every time you will call that function you will create new instance of PDO and open new connection. You might want to move the part that creates PDO instance into the db-config file then use that single instance everytime you are going to create new statement using $pdo->prepare().
3) The use of die. It's common practice to use die or exit when the query goes wrong in examples. But in actual application it would mean the user will see ugly empty page with single sentence saying something went wrong. It's better to throw an exception that will be handled higher in your app. That would let the application to display the page layout with menu and other things even if the requested action failed.
4) You do not set the value to $output variable in your first "Query DB" part of code. Although i'm not sure if you just left it out when copying or if you have it like this in your actual code.
In regards to SQL injection, as long as you parameterize all inputs and white list all dynamic SQL parts, you should be safe.
However, your code has another serious problem. You are silencing errors. PDO::ATTR_ERRMODE should be set to PDO::ERRMODE_EXCEPTION. But, that would leave your code even in a worse state, as you have die all over the place. Don't catch the exceptions unless you have extremely good reason to do so. Read this article https://phpdelusions.net/pdo#errors
Silencing or displaying errors to the user opens up new vectors for exploitation. That is why the best course of action is to leave them alone. In production system you should have the configuration set to never display errors. They will be securely logged on the server.
My website sends an XMLHttpRequest to this PHP script:
<?php
if(isset($_POST))
{
require ('../../PDOConnect.php');
try
{
$insert = $pdo->prepare("INSERT INTO priorities
employeeID, WorkOrderNumber
VALUES (?,?)");
$insert->bindValue(1,$_POST['employeeID'],PDO::PARAM_INT);
$insert->bindValue(2,$_POST['WorkOrderNumber'],PDO::PARAM_INT);
$insert->execute();
echo "try";
}
catch(Exception $e)
{
echo "catch";
echo $e;
}
}
?>
At this point, the priorities table does not exist. I'm expecting the XMLHttpRequest's status to be 500 because the query obviously will always fail. PDO does log the error because PDOConnect contains
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
but I get a 200, not a 500. I'm new to PDO. When I was using MySQLi prepared statements, I would get a 500 back from failed PHP scripts, but PDO acts differently. I want the client to know that the query failed, rather than getting a 200 back and thinking that everything went okay. I get the same results with and without try and catch. Am I failing to understand how PDO works? Do I need to change a PDO setting?
Edit: I added echo "try"; and echo "catch";. The client's responseText is always "try", never "catch". It seems that the catch statement doesn't run. Why is that?
My PDOConnect.php file contains:
<?php
$options =
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
];
$pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8mb4','root','mypassword',$options);
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
?>
Make sure the PDO options are set correctly. It's importand to set the PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION option via the $option parameter of the PDO constructor. Don't set this option via setAttribute(), it's pointless.
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset COLLATE $collate"
];
$pdo = new PDO($dsn, $username, $password, $options);
Then handle the Exception and send the 500 http error code:
try {
// do something
} catch(Exception $ex) {
header('500 Internal Server Error', true, 500);
echo $ex->getMessage();
}
You can also try this in your try...catch syntax to know what error you are getting in your PDO query.
<?php
try {
//pdo query
}
catch(PDOException $e) {
echo 'Exception -> ';
var_dump($e->getMessage());
}
Then note that 200 response means that your Ajax request succeeded. If you're getting a 500 response then check your configuration. The 500 Internal Server Error is a very general HTTP status code. It means something has gone wrong on the website and webserver is unable to specify what exactly, thus failing in fulfilling the request made by the client. This is not related to client and the fault is in the webpage/website requested that resides on server. This status code can be considered as a ‘catch-all’ server error of Web server.
Hi I have the following code :
try {
$sth = $this->container->db->prepare("select x from table");
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
return $result;
} catch (\PDOException $e) {
throw new ServerException("Could not get data");
} catch (\Exception $e) {
return false;
}
using slim 3 with wamp
the problem is when I point to the API(polling every 1 second) I got the following error:
Fatal error: Call to a member function prepare() on boolean in /
2 issues : it throws an error to the client
and it throws an error in php_error.log under wamp and the file becomes bigger
how can I prevent and catch those errors
PDO class:
public function getConnection($dsn, $username, $password) {
$conn = null;
try {
$conn = new PDO($dsn, $username, $password);
//Set common attributes
$conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return $conn;
} catch (PDOException $e) {
return false;
//TODO: flag to disable errors?
throw $e;
}
catch(Exception $e) {
die();
//TODO: flag to disable errors?
throw $e;
}
}
Like many learners, you are taking this matter upside down
You should never actually catch an exception like this.
it throws an error to the client
Disable it for the whole site on the live server. There should be not a single PHP error message shown to the user, no matter if it's PHP exception or a filesystem error. Set display_errors to a negative value and forget this matter for all.
how can I prevent and catch those errors
Again, you should never do anything like this, bluntly catching every error and just dismissing it. It's like using the notorious # operator
it throws an error in php_error.log under wamp and the file becomes bigger
Ok, only this one makes sense. There are two possible solutions:
The best one: configure your mysql server properly so it wouldn't die under such a light load like 1 RPS.
Okay, what you actually want but I still don't recommend as it never pays to sweep the dirt under the rug: catch the exception, then verify if it's one you expect, then do something (i.e. try to reconnect after a short timeout), but re-throw the exception otherwise so you will have an idea when something else would go wrong. For this purpose you should add a condition in the try..catch block that should verify the error, handle it if it's one that you expect or just throw it again otherwise.
Of course, in order to catch a PDOException you have to enable it for PDO.
1) In Slim you should use the container (service factory) to build the PDO object. Example:
$container['db'] = function (Container $container) {
$settings = $container->get('settings');
$host = $settings['db']['host'];
$dbname = $settings['db']['database'];
$username = $settings['db']['username'];
$password = $settings['db']['password'];
$charset = $settings['db']['charset'];
$collate = $settings['db']['collate'];
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset COLLATE $collate"
];
return new PDO($dsn, $username, $password, $options);
};
2) You must set the PDO options into the constructor to make it work. Example:
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];
$pdo = new PDO($dsn, $username, $password, $options);
I realize this is probably super simple but i just started taking peoples advice and im converting a small program from mysql to PDO as an attempt to learn and switch to PDO.
The script is a script that shows you how to build a shopping cart, so keep in mind its focused on a learning audience like myself. Anyway i converted the old script here:
function db_connect()
{
$connection = mysql_pconnect('localhost', 'database_1', 'password');
if(!$connection)
{
return false;
}
if(!mysql_select_db('database_1'))
{
return false;
}
return $connection;
}
to this which does connect fine:
function db_connect() {
//Hostname
$hostname = 'xxx.com';
//username
$username = 'xxx';
//password
$password = 'xxx';
try {
$connection = new PDO("mysql:host=$hostname;dbname=database_1", $username, $password);
}
catch(PDOException $e){
echo $e->getMessage();
}
}
Now in other parts of the script before accessing the database it does this:
$connection = db_connect();
Now i have 2 questions. First is to help me understand better what is going on.
I understand in the original mysql function we connect to the database, if the connection is unsuccessful or the database doesnt exist it returns false. If it does connect to the database then it returns true.
With that i mind i dont understand this:
$connection = db_connect();
Isnt that just assigning true or false to the $connection variable, if so then whats going on in this part of the code.
$price = 0.00;
$connection = db_connect();
if (is_array($cart))
{
foreach($cart as $id => $qty)
{
$query = "SELECT price
FROM products
WHERE products.id = '$id' ";
$result = mysql_query($query);
if($result)
{
$item_price = mysql_result($result, 0, 'price');
$price += $item_price * $qty;
}
}
}
Instead couldn't i just create an include file with the PDO connection and no function and include that at the top of each page i run scripts on. I just don't understand where the $connection = db_connect comes in.
So the 2nd question if my above suggestion is not the answer is how do i return a boolean value from the connection function to return true or false (If i even need to)
There is one essential difference between old mysql and PDO: both these libraries require a resource variable to connect with. If you take a look at mysql_query() function definition, you will notice the second parameter, represents such a resource.
$connection variable returned by your old function by no means contain boolean value but such a resource variable. Which can be used in every mysql_query call.
But while for mysql ext this resource parameter being optional, and used automatically when not set, with PDO you have to address this resource variable explicitly. Means you cannot just call any PDO function anywhere in the code, but only as a method of existing PDO object. Means you have to make this variable available wherever you need PDO.
Thus, you need not a boolean but PDO object.
Here is the right code for the function:
function db_connect()
{
$dsn = "mysql:host=localhost;dbname=test;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
return new PDO($dsn,'root','', $opt);
}
now you can use it this way
$pdo = db_connect();
but note again - unlike with mysql_query(), you have to always use this $pdo variable for your queries.
Further reading is PDO tag wiki
As you guessed from the context, db_connect() is supposed to return the connection object. Your converted version doesn't return anything, which is a problem.
With the mysql module, you can run queries without using the connection object - this is not the case with PDO. You'll need to use the connection object to run any queries -
$result = $connection->query('SELECT * FROM foo');
First off, let me congratulate you for making the effort to learn PDO over mysql_*. You're ahead of the curve!
Now, a few things to understand:
PDO is OO, meaning the connection to the database is represented by a PDO Object.
Your db_connect() function should return the object that gets created.
Passing in the parameters required by PDO will give you more flexibility!
So what we have is:
function db_connect($dsn, $username, $password)
{
$conn = new PDO($dsn, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //This makes sure that PDO will throw PDOException objects on errors, which makes it much easier enter code hereto debug.
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //This disables emulated prepared statements by PHP, and switches to *true* prepared statements in MySQL.
return $conn; //Returns the connection object so that it may be used from the outside.
}
Now, you may have noticed we aren't checking for PDOExceptions inside of the function! That's because you can't handle the error from inside of the function correctly (becuase you don't know what you would want to do? Would you terminate the page? Redirect to an error message?). So you can only know it when you call the function.
So usage:
try {
$connection = db_connect("mysql:host=$hostname;dbname=database", "user", "pass");
}
catch (PDOException $e) {
echo "Database error! " . $e->getMessage();
}
Further Reading!
The PDO Manual entry - is super easy and super useful. I recommend you read all of it.
Goal: to simply fetch array from a MySQL database.
Issue: I am using the $dsn "string variable" as a parameter in the PDO Statement but there appears to be an uncaught exception and it has something to do with invoking the driver or the (PDO->__construct) -- I am not sure. Do you have any ideas on how to fix the $dsn string variable or other areas of this code that would cause it to fail? Thanks in advance.
// Define Database Parameters
$dbhost = "localhost";
$dbname = "x";
$dbuser = "y";
$dbpass = "z";
// Invoke Driver (as a variable string)
$dsn = "mysql:host=$dbhost;dbname=$dbname";
// Connect to newly created db object
$dbh = new PDO($dsn, $dbuser, $dbpass);
// Set the PDO error mode to enable exceptions
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// Execute query to the database
$sql = "SELECT * FROM a_aif_remaining";
$sth = $dbh->prepare($sql);
$sth->execute();
// Present results from query
print("PDO::FETCH_ASSOC: ");
print("Return next row as an array indexed by column name");
$result = $sth->fetch(PDO::FETCH_ASSOC);
print_r($result);
print("");
return $results;
// Close db connection
$dbh = NULL;
?>
Put your code in a try catch block. And see the error message reported. An example of this below:
try
{
if ( !class_exists( 'PDO' ) )
throw new Exception( 'PHP without PDO' );
if ( array_search( PDO::getAvailableDrivers(), 'mysql' ) === false )
throw new Exception( 'PHP without PDO mysql driver' );
$dbh = new PDO( ... );
...
}
catch ( PDOException $e )
{
print $e->getMessage();
}
catch ( Exception $e )
{
print $e->getMessage();
}
There can't be any problem where you're looking for it. Substituting a string with a variable is okay and cannot cause any issues. So, it is somewhere else. Luckily PHP reported of it, but strangely, you paid not much attention to that report.
there appears to be an uncaught exception
Uncaught exceptions often contains the error message.
Most of PHP error messages are quite informative. One have to read them through to get the explanation of the problem. After all, it's the only your source of information. No one can tell you what is wrong on your server but server itself. If you have difficulties with interpreting the error message - it is essential to post it along with your question, to let people interpret it for you. So, every error message you get, should be posted in your question, whole and intact. Simple but very important rule.