I have currently created this code from various tutorials and the PHP Manual (changed personal settings to 123)
$username = "123";
$password = "123";
$host = "localhost";
$dbname = "123";
try {
$dbh = new PDO('mysql:host=localhost;dbname=123', $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected";
}
catch(PDOException $e) {
echo "I'm sorry Charlie, I'm afraid i cant do that.";
file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
$dbh = null;
}
I was just wondering if this is the best/safest way to connect to the database? Other examples i have saw people have uses classes and private and public functions? I am new to PDO and my next steps are to insert, update, and delete data. I have built this before using mysql but thought it would be best to have a full understanding of PDO. Any hints, tips or advice would be great. Thanks!
This is safe but the main problems can occurs while inserting unquoted data (although PDO can be used to do it).
I suggest you to use another database layer (ORM) like Zend_Db or Doctrine, this will make your life really easier and your development safer since they handle some of the tough work for you.
Related
When reading on php.net about MySQL functions. I encountered this message
Warning
This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:
mysqli_connect()
PDO::__construct()
I've read about PDO. How can I update my code to PDO using either MySQL or MSSQL?
I see a lot of code posted on SO implementing my_sql functions. And comments from others (including myself) pressing the questioners to abandon MySQL functions and start using PDO or MySQLI. This post is here to help. You can refer to it as it provides explanation to why they are deprecated and what PDO is, plus a minimal code example to implement PDO.
First of all:
Conversion from mysql functions to PDO is not a simple case of search and replace. PDO is an Object Oriented Programming add on for the PHP language.
That means an other approach in writing the code as with the mysql functions. First why convert?
Why are mysql functions deprecated?
The mysql extension is ancient and has been around since PHP 2.0, released 15 years ago (!!); which is a decidedly different beast than the modern PHP which tries to shed the bad practices of its past. The mysql extension is a very raw, low-level connector to MySQL which lacks many convenience features and is thereby hard to apply correctly in a secure fashion; it's therefore bad for noobs. Many developers do not understand SQL injection and the mysql API is fragile enough to make it hard to prevent it, even if you're aware of it. It is full of global state (implicit connection passing for instance), which makes it easy to write code that is hard to maintain. Since it's old, it may be unreasonably hard to maintain at the PHP core level.
The mysqli extension is a lot newer and fixes all the above problems. PDO is also rather new and fixes all those problems too, plus more.
Due to these reasons* the mysql extension will be removed sometime in the future.
source Deceze
How to implement PDO
PDO offers one solution for connecting to multiple databases. This answer covers only MySQL and MSSQL servers.
Connecting to a MySQL database, prerequisites
This is fairly simple and doesn't require any pre set-up of PHP. Modern PHP installations are standard shipped with a module that allows PDO connections to MySQL servers.
The module is php_pdo_mysql.dll
Connecting to a MSSQL database, prerequisites
This is a more advanced set-up. You need php_pdo_sqlsrv_##_ts.dll or php_pdo_sqlsrv_##_nts.dll drivers. They are version specific hence the ##. At the moment of writing, Microsoft has released
official drivers for PHP 5.5.x. The 5.6 drivers aren't yet officially released by Microsoft, but are available as non-official builds by others.
The module is php_pdo_sqlsrv_##_ts.dll for the thread safe variant
The module is php_pdo_sqlsrv_##_nts.dll for the non-thread safe variant
Connecting to a database using PDO
To connect to a database you need to create a new PDO instance from the PDO construct.
$connection = new PDO(arguments);
The PDO constructor takes 1 required arguments and 3 optional.
DSN or Data Source Name, mostly this is a string containing information about the driver, host and database name. Since PHP 7.4 it can also include username and password.
Username
Password
Options
Connecting to MySQL
$dsn = 'mysql:dbname=databasename;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
$dbh = new PDO($dsn, $user, $password);
Let's take a look at $dsn: First it defines the driver (mysql). Then the database name and finally the host.
Connecting to MSSQL
$dsn = 'sqlsrv:Server=127.0.0.1;Database=databasename';
$user = 'dbuser';
$password = 'dbpass';
$dbh = new PDO($dsn, $user, $password);
Let's take a look at $dsn: First it defines the driver (sqlsrv). Then the host and finally the database name.
When you create the instance a connection is made to the database. You only have to do this once during the execution of a PHP script.
You need to wrap the PDO instance creation in a try-catch clause. If the creation fails a back trace is shown revealing critical information about your application, like username and password. To avoid this catch the errors.
try
{
$connection = new PDO($dsn, $user, $password);
}
catch( PDOException $Exception )
{
echo "Unable to connect to database.";
exit;
}
To throw errors returned by your SQL server add this options to your PDO instance using setAttribute: $connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Performing queries
PDO uses prepared statements. This is a real difference between PDO's approach and mysql functions. The latter was very susceptible to SQL-INJECTION. One would build a query like this:
$SQL = 'SELECT ID FROM users WHERE user = '.$username ;
When a malicious website or person posts the username injector; DROP TABLE users. The results will be devastating. You needed to proof your code by escaping and encapsulating strings and variables with quotes. This had to be done
for every query. On larger websites or poorly maintained code the risk of having a form that allowed SQL injection could become very high. Prepared statements eliminates the chance of first tier SQL injection like the example above.
The PDO drivers act as a man-in-the-middle between your PHP-server and database server, called a data-access abstraction layer. It doesn't rewrite your SQL queries, but do offer a generic way to connect to multiple database types
and handles the insertion of variables into the query for you. Mysql functions constructed the query on execution of the PHP code. With PDO the query actually gets build on the database server.
A prepared SQL example:
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
Note the difference; Instead of a PHP variable using $ outside the string, we introduce a variable using : within the string. Another way is:
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = ?';
How to perform the actual query
Your PDO instance provides two methods of executing a query. When you have no variables you can use query(), with variables use prepare(). query() is immediately executed upon calling. Please note the object oriented way of the call (->).
$result = $connection->query($SQL);
The prepare method
The prepare method takes two arguments. The first is the SQL string and the second are options in the form of an Array. A basic example
$connection->prepare($SQL, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
In our SQL string example we've used a named variable called :username. We still need to bind a PHP variable, integer or string to it. We can do this in two ways. Either build an array containing the named variables as key or use the method bindParam or bindValue.
I will explain the array variant and the method bindValue for the sake of simplicity.
Array
You can do something like this for named variables, where you provide the variable as array key:
$queryArguments = array(':username' => $username);
And this for indexed variables (?):
$queryArguments = array($username);
When you have added all the variables you need you can call upon the method execute() to perform the query. Thereby passing the array as argument to the function execute.
$result = $connection->execute($queryArguments);
bindValue
The bindValue method allows you to bind values to the PDO instance. The method takes two required arguments and one optional. The optional arguments set the data-type of the value.
For named variables:
$connection->bindValue(':username', $username);
For indexed variables:
$connection->bindValue(1, $username);
After binding the values to the instance, you can call upon execute without passing any arguments.
$result = $connection->execute();
NOTE: You can only use a named variable once! Using them twice will result in a failure to execute the query. Depending on your settings this will or will not throw an error.
Fetching the results
Again I will only cover the basics for fetching results from the returned set. PDO is a fairly advanced add-on.
Using fetch and fetchAll
If you did a select query or executed a stored procedure that returned a result set:
fetch
fetch is a method that could take up to three optional arguments. It fetches a single row from the result set. By default it returns an array containing the column names as keys and indexed results.
Our example query could return something like
ID EMAIL
1 someone#example.com
fetch will return this as:
Array
(
[ID] => 1
[0] => 1
[EMAIL] => someone#example.com
[1] => someone#example.com
)
To echo all output of a result set:
while($row = $result->fetch())
{
echo $row['ID'];
echo $row['EMAIL'];
}
There are other options you can find here: fetch_style;
fetchAll
Fetches all rows in a single array. Using the same default option as fetch.
$rows = $result->fetchAll();
If you used a query that didn't return results like a insert or update query you can use the method rowCount to retrieve the amount of rows affected.
A simple class:
class pdoConnection {
public $isConnected;
protected $connection;
public function __construct($dsn, $username, $password, $options = array()) {
$this->isConnected = true;
try {
$this->connection = new PDO($dsn, $username, $password, $options);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); //sets the default to return 'named' properties in array.
} catch (PDOException $e) {
$this->isConnected = false;
throw new Exception($e->getMessage());
}
}
public function disconnect() {
$this->connection = null;
$this->isConnected = false;
}
public function query($SQL) {
try {
$result = $this->connection->query($SQL);
return $result;
} catch (PDOException $e) {
throw new PDOException($e->getMessage());
}
}
public function prepare($SQL, $params = array()) {
try {
$result = $this->connection->prepare($SQL);
$result->execute($params);
return $result;
} catch (PDOException $e) {
throw new PDOException($e->getMessage());
}
}
}
How to use:
$dsn = 'mysql:dbname=databasename;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
$db = new pdoConnection($dsn, $user, $password);
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
$result = $db->prepare($SQL, array(":username" => 'someone'));
while($row = $result->fetch())
{
echo $row['ID'];
echo $row['EMAIL'];
}
When reading on php.net about MySQL functions. I encountered this message
Warning
This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:
mysqli_connect()
PDO::__construct()
I've read about PDO. How can I update my code to PDO using either MySQL or MSSQL?
I see a lot of code posted on SO implementing my_sql functions. And comments from others (including myself) pressing the questioners to abandon MySQL functions and start using PDO or MySQLI. This post is here to help. You can refer to it as it provides explanation to why they are deprecated and what PDO is, plus a minimal code example to implement PDO.
First of all:
Conversion from mysql functions to PDO is not a simple case of search and replace. PDO is an Object Oriented Programming add on for the PHP language.
That means an other approach in writing the code as with the mysql functions. First why convert?
Why are mysql functions deprecated?
The mysql extension is ancient and has been around since PHP 2.0, released 15 years ago (!!); which is a decidedly different beast than the modern PHP which tries to shed the bad practices of its past. The mysql extension is a very raw, low-level connector to MySQL which lacks many convenience features and is thereby hard to apply correctly in a secure fashion; it's therefore bad for noobs. Many developers do not understand SQL injection and the mysql API is fragile enough to make it hard to prevent it, even if you're aware of it. It is full of global state (implicit connection passing for instance), which makes it easy to write code that is hard to maintain. Since it's old, it may be unreasonably hard to maintain at the PHP core level.
The mysqli extension is a lot newer and fixes all the above problems. PDO is also rather new and fixes all those problems too, plus more.
Due to these reasons* the mysql extension will be removed sometime in the future.
source Deceze
How to implement PDO
PDO offers one solution for connecting to multiple databases. This answer covers only MySQL and MSSQL servers.
Connecting to a MySQL database, prerequisites
This is fairly simple and doesn't require any pre set-up of PHP. Modern PHP installations are standard shipped with a module that allows PDO connections to MySQL servers.
The module is php_pdo_mysql.dll
Connecting to a MSSQL database, prerequisites
This is a more advanced set-up. You need php_pdo_sqlsrv_##_ts.dll or php_pdo_sqlsrv_##_nts.dll drivers. They are version specific hence the ##. At the moment of writing, Microsoft has released
official drivers for PHP 5.5.x. The 5.6 drivers aren't yet officially released by Microsoft, but are available as non-official builds by others.
The module is php_pdo_sqlsrv_##_ts.dll for the thread safe variant
The module is php_pdo_sqlsrv_##_nts.dll for the non-thread safe variant
Connecting to a database using PDO
To connect to a database you need to create a new PDO instance from the PDO construct.
$connection = new PDO(arguments);
The PDO constructor takes 1 required arguments and 3 optional.
DSN or Data Source Name, mostly this is a string containing information about the driver, host and database name. Since PHP 7.4 it can also include username and password.
Username
Password
Options
Connecting to MySQL
$dsn = 'mysql:dbname=databasename;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
$dbh = new PDO($dsn, $user, $password);
Let's take a look at $dsn: First it defines the driver (mysql). Then the database name and finally the host.
Connecting to MSSQL
$dsn = 'sqlsrv:Server=127.0.0.1;Database=databasename';
$user = 'dbuser';
$password = 'dbpass';
$dbh = new PDO($dsn, $user, $password);
Let's take a look at $dsn: First it defines the driver (sqlsrv). Then the host and finally the database name.
When you create the instance a connection is made to the database. You only have to do this once during the execution of a PHP script.
You need to wrap the PDO instance creation in a try-catch clause. If the creation fails a back trace is shown revealing critical information about your application, like username and password. To avoid this catch the errors.
try
{
$connection = new PDO($dsn, $user, $password);
}
catch( PDOException $Exception )
{
echo "Unable to connect to database.";
exit;
}
To throw errors returned by your SQL server add this options to your PDO instance using setAttribute: $connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Performing queries
PDO uses prepared statements. This is a real difference between PDO's approach and mysql functions. The latter was very susceptible to SQL-INJECTION. One would build a query like this:
$SQL = 'SELECT ID FROM users WHERE user = '.$username ;
When a malicious website or person posts the username injector; DROP TABLE users. The results will be devastating. You needed to proof your code by escaping and encapsulating strings and variables with quotes. This had to be done
for every query. On larger websites or poorly maintained code the risk of having a form that allowed SQL injection could become very high. Prepared statements eliminates the chance of first tier SQL injection like the example above.
The PDO drivers act as a man-in-the-middle between your PHP-server and database server, called a data-access abstraction layer. It doesn't rewrite your SQL queries, but do offer a generic way to connect to multiple database types
and handles the insertion of variables into the query for you. Mysql functions constructed the query on execution of the PHP code. With PDO the query actually gets build on the database server.
A prepared SQL example:
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
Note the difference; Instead of a PHP variable using $ outside the string, we introduce a variable using : within the string. Another way is:
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = ?';
How to perform the actual query
Your PDO instance provides two methods of executing a query. When you have no variables you can use query(), with variables use prepare(). query() is immediately executed upon calling. Please note the object oriented way of the call (->).
$result = $connection->query($SQL);
The prepare method
The prepare method takes two arguments. The first is the SQL string and the second are options in the form of an Array. A basic example
$connection->prepare($SQL, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
In our SQL string example we've used a named variable called :username. We still need to bind a PHP variable, integer or string to it. We can do this in two ways. Either build an array containing the named variables as key or use the method bindParam or bindValue.
I will explain the array variant and the method bindValue for the sake of simplicity.
Array
You can do something like this for named variables, where you provide the variable as array key:
$queryArguments = array(':username' => $username);
And this for indexed variables (?):
$queryArguments = array($username);
When you have added all the variables you need you can call upon the method execute() to perform the query. Thereby passing the array as argument to the function execute.
$result = $connection->execute($queryArguments);
bindValue
The bindValue method allows you to bind values to the PDO instance. The method takes two required arguments and one optional. The optional arguments set the data-type of the value.
For named variables:
$connection->bindValue(':username', $username);
For indexed variables:
$connection->bindValue(1, $username);
After binding the values to the instance, you can call upon execute without passing any arguments.
$result = $connection->execute();
NOTE: You can only use a named variable once! Using them twice will result in a failure to execute the query. Depending on your settings this will or will not throw an error.
Fetching the results
Again I will only cover the basics for fetching results from the returned set. PDO is a fairly advanced add-on.
Using fetch and fetchAll
If you did a select query or executed a stored procedure that returned a result set:
fetch
fetch is a method that could take up to three optional arguments. It fetches a single row from the result set. By default it returns an array containing the column names as keys and indexed results.
Our example query could return something like
ID EMAIL
1 someone#example.com
fetch will return this as:
Array
(
[ID] => 1
[0] => 1
[EMAIL] => someone#example.com
[1] => someone#example.com
)
To echo all output of a result set:
while($row = $result->fetch())
{
echo $row['ID'];
echo $row['EMAIL'];
}
There are other options you can find here: fetch_style;
fetchAll
Fetches all rows in a single array. Using the same default option as fetch.
$rows = $result->fetchAll();
If you used a query that didn't return results like a insert or update query you can use the method rowCount to retrieve the amount of rows affected.
A simple class:
class pdoConnection {
public $isConnected;
protected $connection;
public function __construct($dsn, $username, $password, $options = array()) {
$this->isConnected = true;
try {
$this->connection = new PDO($dsn, $username, $password, $options);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); //sets the default to return 'named' properties in array.
} catch (PDOException $e) {
$this->isConnected = false;
throw new Exception($e->getMessage());
}
}
public function disconnect() {
$this->connection = null;
$this->isConnected = false;
}
public function query($SQL) {
try {
$result = $this->connection->query($SQL);
return $result;
} catch (PDOException $e) {
throw new PDOException($e->getMessage());
}
}
public function prepare($SQL, $params = array()) {
try {
$result = $this->connection->prepare($SQL);
$result->execute($params);
return $result;
} catch (PDOException $e) {
throw new PDOException($e->getMessage());
}
}
}
How to use:
$dsn = 'mysql:dbname=databasename;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
$db = new pdoConnection($dsn, $user, $password);
$SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
$result = $db->prepare($SQL, array(":username" => 'someone'));
while($row = $result->fetch())
{
echo $row['ID'];
echo $row['EMAIL'];
}
Pre-emptive apology: This post contains basic questions.However, I have searched and I have not found an answer, if there is one...sorry.
I am following some youtube tutorials for making a basic ajax web chat, and in the tutorial the person is using MySQLi to connect to the DB. I want to create the same ajax chat application except I want to use PDO instead of MySQLi.
The person uses these two files:
config.php
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'bucky_chat');
define('DB_PASSWORD', '123456');
define('DB_NAME', 'bucky_chat');
?>`
chat.class.php
<?php
require_once('config.php');
require_once('error_handler.php');
class Chat {
private $mysqli;
//constructor opens DB connection
function __construct(){
$this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
}
//destructor closes db connection
function __destruct(){
$this->mysqli->close();
}
}
?>
I'm trying to replicate the above snippets with PDO. The problem is that I'm not sure how to adapt the PDO examples I have looked at to do this.
First of all I'm confused as to why he defined these things in a separate file.. are there any benefits in doing this?
In another PDO tutorial I am looking at I see it can be done the followings way:
<?php
$config['db'] = array(
'host' => 'localhost',
'username' => '',
'password' => '',
'dbname' => ''
);
$db = new PDO('mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['db_name'], $config['db']['username'], $config['db']['password']);
//some code
$db = null; //closes connection
?>
`
I think this is what I need to use (in a try catch block), but why does he put these things in an array? it seems to over complicate things... why not just variables? But does this code replicate the mysqli example? Howcome I don't see __construct() being used with PDO?
Some minor questions...
When creating a website with a user, is there a standard place to store DB connection?
Any book recommendations?
Sorry for all these questions, All help is strongly appreciated!
To answer your questions:
First of all I'm confused as to why he defined these things in a separate file
The authentication details are defined in a second file because if you create another query script, now both scripts can include the authentication details. If the authentication details change, you only need to update one file. If you are just writing a simple application, than just keep everything in one file.
but why does he put these things in an array
I think this is just done in-case the authentication details are needed someone else in the script (much like the defined globals from your first sample). Its often best practice to define parameters into variables (even if you use the variable once). This way, if you typo a variable, you will get an error; versus copy and pasting the same string over and over again.
Howcome I don't see __construct() being used with PDO
When ever you create a new object in PHP, you do not need to call __construct, it is called automatically with the "new" statement.
$PDOConnection = new PDO($dsn, $username, $password);
When creating a website with a user, is there a standard place to store DB connection
Definitely make sure the authentication details are stored in an inaccessible file to the public. The connection object has no harm to be accessed by the public (unless of course you need to authenticate the client (website user) before establishing a database connection). Is is best practice to always begin your (secure) PHP files with:
<?php
BUT... never end the file with "?>". If an extra character is inserted after the "?>" on accident, your web server could display your whole script to the world (of course your Apache, etc... would have to be configured wrong). Like I said... best practices.
Any book recommendations?
Googleing "php arcitechture best practices" may help.
You are confusing WAY TOO MUCH things that can be explained in one answer. you don't even know what to ask.
Please, don't take the art of programming as a some sort of cheap trick one can learn in 2 hours. To write a AJAX-based chat one need to learn for at least several months. To learn by understanding, not by copy-pasting. To learn step by step, going from variables to arrays, from arrays to functions, from functions to classes and so on - not by throwing all the code they find in one bowl and then asking on SO how to deal with all that. One cannot get to another step without having understand a previous one. And of course all these youtube tutorials are definitive pieces of useless rubbish.
some of your confusions are:
__construct() method actually has nothing to do with PDO. Nor with mysql. this is a Chat class method. And method which is all wrong. Chat class shouldn't create its own connection but use already created one.
This thing on variables vs. array vs. constants doesn't really matter. To have connection options in a separate file is a good thing but nonetheless you need to have a connection code in the separate file as well, to avoid writing connection code in the every file.
You should not use this code in a try catch block (unless you have an idea what to do in case of error, which I doubt you have).
Before starting for a chat, you have to learn smaller, simpler applications, like telephone book or the like, to learn basic database operations, from which you'll be later able to build ANY application, like any house can be built of bricks.
PDO basics you can get right here, in the tag wiki. But OOP basics is not that easy.
First the reason you define config in different file is so that you can just include that file instead of writing the database configuration anytime you want database access. It is preferred best practice.
you can do:
try
{
$PDOConnection = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.'', DB_USER, DB_PASS);
$PDOConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Do you stuffs
$PDOConnection = null;
}
catch(PDOException $e)
{
//Do something with error
}
Why not just do:
<?php
$hostname = 'host';
$dbname = 'dbname';
$username = 'uname';
$password = 'pw';
try {
$db = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $ex) {
echo "An Error occurred!";
}
?>
In a separate PHP file I call mine dbPDO.php and then have:
require_once("dbPDO.php");
In your PHP pages. And then run queries by doing:
EDIT: to condense my answer.
$username = $_POST['username'];
$stmt = $db->prepare("SELECT field1, field2, field3, etc FROM mytable WHERE username = :username");
$stmt->bindParam(':username', $username);
$stmt->execute();
while ($r = $stmt->fetch()) {
$field1 = $r['field1'];
$etc = $r['etc'];
}
Make sure you bindParam and use the ':' in the query. Don't just put WHERE username = $username or WHERE username = $_POST['username'] That would led you prone to SQL Injection. Also, I didn't show it here, but you should have some sort of exemption handling for each query. I place the whole query in a Try/Catch, but I hear there are other ways to deal with it. I personally think its personal preference.
First of all you don't need an array nor variables, you can directly input the configuration..like:
try { //try connection
//common db
$db = new PDO('mysql:host=localhost;dbname=some_db_name', 'some_usernane', 'some_pass');
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) { //connection failed
die("Oh no! It seems we took too long to respond, we are sorry for that..");
}
Secondly _constructor() means that whenever the class Chat is called everything in the _constructor() is executed .
Here is a good tutorial for PDO http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
On the existing system its use old MySQL functions.. I would like to replace it all to PDO but it would take a long time and a lot of testing.
Is it possible to mix PDO and MySQL Functions on the existing system? For example new pages/php files will use PDO... All the old files will still use old MySQL for time being and will be replaced slowly as system will continue to update..
Yes, it is perfectly fine to use both at the same time. Keep in mind, though, that you would need a seperate connection for either type and beware of the implications that arise from such an approach.
I am new to SO but I have faced this problem too. Many people find it troublesome to switch from mysql_* to PDO.
In my case I was using a separate connection.php that stored functions to connect to database and returned the handle
function connect()
{
$cn = mysql_connect("localhost","username","pass" );
$select = mysql_select_db("dbname", $cn);
return($cn);
}
//For PDO
function pdoconnect()
{
$db="";
try
{
$db=new PDO("mysql:host=localhost;dbname=dbname", "username", "pass");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $er)
{
print("errr".$er."<br />");
return(1);
}
return($db);
}
while for old functions I used $cn=connect();.
I switched to $cn=pdoconnect(); for new ones.
This worked because I was already using connect.php in old files as well.
I am still learning mostly from books I buy, but today I leart that my book is old even though I bought it this year concerning programming in PHP. Now I know that mysql_* commands in PHP are deprecated and should be replaced with more secure and stable prepared statements and PDO. So I put myself to rewrite all my web according to it and maybe I will need some advices from you how to do it properly and working from you all more experienced guys :)
So I will start my rewrite with only main part (connect to db and choosing DB) in here (the rest I can do on my own with google and manuals). I will write here my old script and ask you if I am doing everything right and not missing anything and I hope this could be some good manual/answer for other people as well. So lets start.
So in config I have something like this:
$db = new dbConn('127.0.0.1', 'root', 'pass', 'people', 'animals');
Which should be like this:
$db = new PDO('mysql:host=127.0.0.1;dbname=people;charset=UTF-8', 'root', 'pass');
Right? But when I need to choose database later should i do it without dbname=people;? But how to choose database later?
Here is my one and only script to rewrite which is basic in most web projects and I hope it will bring not only me some understanding how new PDO system really works:
class dbConn
{
public function __construct($server, $user, $pass, $db_people, $db_animals)
{
if (!empty($server) && !empty($user) && !empty($pass) && !empty($db_people) && !empty($db_animals))
{
$this->server = $server;
$this->user = $user;
$this->pass = $pass;
$this->db_people = $db_people;
$this->db_animals = $db_animals;
$this->connect();
}
else
{
die("Set up connection to db");
}
}
public function connect()
{
$this->conn = mysql_connect($this->server, $this->user, $this->pass) or die ('cannot connect to MySQL');
}
public function selectDb($database)
{
switch($database)
{
case 'people':
mysql_select_db($this->db_people, $this->conn) or die ('cannot connect to database '.$this->db_people.'.');
mysql_query("SET NAMES 'utf8'");
break;
case 'animals':
mysql_select_db($this->db_animals, $this->conn) or die ('cannot connect to database '.$this->db_animals.'.');
mysql_query("SET NAMES 'utf8'");
}
}
public function __destruct()
{
if (!empty($this->conn))
{
mysql_close($this->conn);
}
}
}
So from what I know from Google and Wiki - functions like public function __construct and public function __destruct() should not be needed anymore, right? The same with functions like public function connect() SO only whats left is public function selectDb($database) but i have no idea how to do this correctly without damading all connection to database. Because in rest of my code (not mentioned here) I can easily choose database by this code: $this->db->selectDb("people"); But with prepared statements I do not know if this is even possible in easy way. I hope some advices around this from you will help me and other users understand this new code better. Other parts in code you may have are eplained in this PDO Tutorial for MySQL Developers. Thank you.
Actually, a simple, sweet and short: Yes, not necessary any longer.
Let's review the code not that we have lost something:
__construct - The constructor merely contained all the configuration. PDO has a much easier concept here, a connection string containing the most information:
mysql:host=127.0.0.1;dbname=people;charset=UTF-8
Also PDO provides the constructor for use ready-made, so double not necessary.
connect - The connection function is not necessary any longer as well. This is done by instantiating PDO already. You can look for exceptions, the PHP manual has an example on it's constructor page.
selectDb - This complicated function is not needed any longer as well. Wow, the third function we can just drop because of the PDO connection string. Much power with so less characters. Cheers!
__destruct - The destructor. Let's be fair: MySQL did not need this as well. However with PDO we get it for free - without writing a single line of code.
Looks good! You managed to migrate from that obscure database class to PDO by removing outdated code! Congratulations:
$db = new PDO('mysql:host=127.0.0.1;dbname=people;charset=UTF-8', 'root', 'pass');
If you now think, what about if I want to have database class on my own? Well you can do that, because you can extend from PDO (yes that works!):
class DB extends PDO
{
... my super-new-shiny-code
}
Why you might want to do that? No idea, but maybe it's more fluent for your code. If you're looking for a better code-example, I have one at PHP/MySQL Table with Hyperlinks.
I think the easiest way to switch the database inside your application will be:
$pdo_instance->query("USE people");
and
$pdo_instance->query("USE animals");
or the maybe better (and cleaner) way might be
$db_people = new PDO('mysql:host=127.0.0.1;dbname=people;charset=UTF-8', 'root', 'pass');
and
$db_animals = new PDO('mysql:host=127.0.0.1;dbname=animals;charset=UTF-8', 'root', 'pass');
If you mark a database in your class active, you can access the data with $db_people->query() or $db_animals->query().