Friday, January 20, 2017

How to run Redis server as daemon

 
 Want to run redis-server in background nonstop use below command
 
 
"redis-server --daemonize yes " 
 
Check if the process started or not:

ps aux | grep redis-server

 

Tuesday, November 8, 2016

Securely Communicating with Remote Servers via PHP



PHP has an SSH2 library which provides access to resources (shell, remote exec, tunneling, file transfer) on a remote machine using a secure cryptographic transport. Objectively, it is a tedious and highly frustrating task for a developer to implement it due to its overwhelming configuration options and complex API with little documentation.

The phpseclib (PHPSecure Communications Library) package has a developer friendly API. It uses some optional PHP extensions if they’re available and falls back on an internal PHP implementation otherwise. To use this package, you don’t need any non-default PHP extensions installed.

Installation

composer require phpseclib/phpseclib
This will install the most recent stable version of the library via Composer.

Use-cases

Before diving in blindly, I’d like to list some use-cases appropriate for using this library:
  1. Executing deployment scripts on a remote server
  2. Downloading and uploading files via SFTP
  3. Generating SSH keys dynamically in an application
  4. Displaying live output for remote commands executed on a server
  5. Testing an SSH or SFTP connection

Connecting to the Remote Server

Using phpseclib, you can connect to your remote server with any of the following authentication methods:
  1. RSA key
  2. Password Protected RSA key
  3. Username and Password (Not recommended)

RSA Key

We will assume that you have a secure RSA key already generated. If you are not familiar with generating a secure RSA key pair, you can go through this article. For a video explanation, you can refer to Creating and Using SSH Keys from Servers For Hackers.
To log in to a remote server using RSA key authentication:
namespaceApp;

    usephpseclib\Crypt\RSA;
    usephpseclib\Net\SSH2;

    $key = new RSA();
    $key->loadKey(file_get_contents('privatekey'));

    //Remote server's ip address or hostname
    $ssh = new SSH2('https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e0%2e1');

    if (!$ssh->login('username', $key)) {
        exit('Login Failed');
    }

Password Protected RSA Key

If your RSA keys are password protected, do not worry. Phpseclib takes care of this particular use case:
namespaceApp;

    usephpseclib\Crypt\RSA;
    usephpseclib\Net\SSH2;

    $key = new RSA();
    $key->setPassword('your-secure-password');
    $key->loadKey(file_get_contents('privatekey'));

    //Remote server's ip address or hostname
    $ssh = new SSH2('https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e0%2e1');

    if (!$ssh->login('username', $key)) {
        exit('Login Failed');
    }

Username and Password

Alternatively, to log in to your remote server using a username and password (we don’t recommend this practice):
namespaceApp;

    usephpseclib\Net\SSH2;

    //Remote server's ip address or hostname
    $ssh = new SSH2('https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e0%2e1');

    if (!$ssh->login('username', 'password')) {
        exit('Login Failed');
    }
For other options such as No Authentication or Multi-Factor authentication please refer to the documentation

Executing Commands on the Remote Server

The code to execute commands on a remote server is pretty simple. You call the $ssh->exec($cmd) method with the command to execute as the parameter.
namespaceApp;

    usephpseclib\Crypt\RSA;
    usephpseclib\Net\SSH2;

    $key = new RSA();
    $key->loadKey(file_get_contents('privatekey'));

    //Remote server's ip address or hostname
    $ssh = new SSH2('https://www.linkedin.com/redir/invalid-link-page?url=192%2e168%2e0%2e1');

    if (!$ssh->login('username', $key)) {
        exit('Login Failed');
    }

    $ssh->exec('ls -la');

Executing Multiple Commands on Remote Server

In real life applications, we rarely execute a single command. We often need to traverse around the server using cd and execute many other commands. If you try to execute multiple commands on the remote server as below, it won’t give you the desired output:
$ssh->exec('pwd'); //outputs /home/username

    $ssh->exec('cd mysite.com');

    $ssh->exec('pwd'); //outputs /home/username
The reason for above is that a call to the exec method does not carry state forward to the next exec call. To execute multiple commands without losing state:
$ssh->exec('cd /home/username; ls -la'); //Lists all files at /home/username
You can append as many commands as you wish with a semicolon or new line character PHP_EOL.
For example, if you want to run a full deployment script for Laravel:
$ssh->exec(
          "git pull origin master" . PHP_EOL
            . "composer install --no-interaction --no-dev --prefer-dist" . PHP_EOL
            . "composer dump-autoload -o" . PHP_EOL
            . "php artisan optimize" . PHP_EOL
            . "php artisan migrate --force"
    );

Exiting on First Error

In the above script, the whole set of commands is executed as a single shell script. Every command will be executed, even if some of them fail, just like in a regular shell script. As a default, this is fine, but if we need to exit on the first error, we have to alter our bash script. This is not something specific to phpseclib, it is related to bash scripting.
If you put a set -e option at the beginning of the script, the script will terminate as soon as any command in the chain returns a non-zero value.
For example, the modified version of the above deployment script would be
$ssh->exec(
        "set -e" . PHP_EOL
            . "git pull origin master" . PHP_EOL 
            . "composer install --no-interaction --no-dev --prefer-dist" . PHP_EOL
            . "composer dump-autoload -o" . PHP_EOL
            . "php artisan optimize" . PHP_EOL
            . "php artisan migrate --force"
    );
The above script will terminate if any of the commands results in an error.

Gathering Output

The exec method returns the output of your remote script:
$output = $ssh->exec('ls -la');
    echo$output;
Sometimes, however, it does not return the whole output. You can overcome this by passing a closure as a second argument to the exec method to make sure that any uncaught output will also be returned.
$ssh->exec(
        $deployment_script, function($str){
            $output .= $str;
    });

    echo $output;
Note: Error output, if any, will also be returned by the exec method or the underlying closure.

Displaying Live Output

If you want to execute the script via console commands and display live output, you can achieve this by echoing the output in the underlying closure.
$ssh->exec($deployment_script, function($str){
        echo $str;
    });
If you want to display it in a web browser, you need to flush (send) the output buffer with ob_flush().
$ssh->exec(
        $deployment_script, function($str){
            echo $str;
            flush();
            ob_flush();
    });

Other Configuration Options

It’s also possible to set many other available configuration options. You can call them as $ssh->{option}.
For example: $ssh->setTimeout(100).
All the options we haven’t covered yet are in the table below:

Option Use case

  1. `setTimeout($seconds)` `$ssh->exec('ping https://www.linkedin.com/redir/invalid-link-page?url=127%2e0%2e0%2e1');` on a Linux host will never return and will run indefinitely. `setTimeout()` makes it so it’ll timeout. Setting `$timeout` to false or 0 will mean there is no timeout.
  2. `write($cmd)` Inputs a command into an interactive shell.
  3. `read()` Returns the output of an interactive shell
  4. `isTimeout()` Return true if the result of the last `$ssh->read()` or `$ssh->exec()` was due to a timeout. Otherwise it will return false.
  5. `isConnected()` Returns true if the connection is still active
  6. `enableQuietMode()` Suppresses stderr so no errors are returned
  7. `disableQuietMode()` Includes stderr in output
  8. `isQuiteModeEnabled()` Returns true if quiet mode is enabled
  9. `enablePTY()` Enable request-pty when using `exec()`
  10. `disablePty()` Disable request-pty when using `exec()`
  11. `isPTYEnabled()` Returns true if request-pty is enabled
  12. `getLog()` Returns a log of the packets that have been sent and received.
  13. `getServerPublicHostKey()` Returns the server public host key. Returns false if the server signature is not signed correctly with the public host key.
  14. `getExitStatus()` Returns the exit status of an SSH command or false.
  15. `getLanguagesClient2Server()` Return a list of the languages the server supports, when receiving stuff from the client.
  16. `getLanguagesServer2Client()` Return a list of the languages the server supports, when sending stuff to the client.
  17. `getCompressionAlgorithmsServer2Client()` Return a list of the compression algorithms the server supports, when sending stuff to the client.
  18. `getCompressionAlgorithmsClient2Server()` Return a list of the compression algorithms the server supports, when receiving stuff from the client.
  19. `getMACAlgorithmsServer2Client()` Return a list of the MAC algorithms the server supports, when sending stuff to the client.
  20. `getMACAlgorithmsClient2Server()` Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
  21. `getEncryptionAlgorithmsServer2Client()` Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
  22. `getEncryptionAlgorithmsClient2Server()` Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
  23. `getServerHostKeyAlgorithms()` Return a list of the host key (public key) algorithms the server supports. `getKexAlgorithms()` Return a list of the key exchange algorithms the server supports. Alternatives
LIBSSH2 – The SSH library – The library provides similar functionality, but is a little less intuitive to use, and it requires you to have libssh2 installed on the server, which most shared hosts don’t have.

Summary

In this article, we introduced phpseclib, a package which provides an alternative for SSH2. We have covered the configuration options necessary to get started, and the table above should help you fill in the gaps and give an overview of other configuration options available to you.

Thursday, March 31, 2011

Introduction to PHP PDO

Introduction to PHP PDO
(PHP Data Objects)


1. What is PDO
2. What Databases does PDO support
3. Where do I begin?
4. Connect to a Database
* Connect to PgSQL
* Connect to SQLite
* Connect to MySQL
* Connect to Firebird
* Connect to Informix
* Connect to Oracle
* Connect to ODBC
* Connect to DBLIB
* Connect to IBM
5. There is no five
6. Close a Database Connection
7. Query a Database
* INSERT
* SELECT
* UPDATE
8. Fetch Modes
* FETCH ASSOC
* FETCH NUM
* FETCH BOTH
* FETCH OBJECT
* FETCH LAZY
* FETCH CLASS
* FETCH INTO
9. Error Handling
10. Prepared Statements
11. Transactions
12. Get Last Insert ID
13. Global Instance
14. Conclusions

What is PDO.

PDO is a PHP extension to formalise PHP's database connections by creating a uniform interface. This allows developers to create code which is portable across many databases and platforms. PDO is _not_ just another abstraction layer like PearDB although PearDB may use PDO as a backend. Those of you familiar with Perls DBI may find the syntax disturbingly familiar.
Note: Your must read the section on Error Handling to benifit from this tutorial

During this tutorial we will be using a database called animals, which, as you might have guessed, is a database of animals, genius! The animals table is described here.
CREATE TABLE animals ( animal_id MEDIUMINT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
animal_type VARCHAR(25) NOT NULL,
animal_name VARCHAR(25) NOT NULL
) ENGINE = MYISAM ;

INSERT INTO `animals` (`animal_id`, `animal_type`, `animal_name`) VALUES
(1, 'kookaburra', 'bruce'),
(2, 'emu', 'bruce'),
(3, 'goanna', 'bruce'),
(4, 'dingo', 'bruce'),
(5, 'kangaroo', 'bruce'),
(6, 'wallaby', 'bruce'),
(7, 'wombat', 'bruce'),
(8, 'koala', 'bruce');
What databases does PDO support?

PDO supports many of the popular databases as seen on the list below.

* DBLIB: FreeTDS / Microsoft SQL Server / Sybase
* Firebird (http://firebird.sourceforge.net/): Firebird/Interbase 6
* IBM (IBM DB2)
* INFORMIX - IBM Informix Dynamic Server
* MYSQL (http://www.mysql.com/): MySQL 3.x/4.0
* OCI (http://www.oracle.com): Oracle Call Interface
* ODBC: ODBC v3 (IBM DB2 and unixODBC)
* PGSQL (http://www.postgresql.org/): PostgreSQL
* SQLITE (http://sqlite.org/): SQLite 3.x

To see if the PDO driver is available for your database, check phpinfo() and you should have a section named PDO and another pdo_mysql or pdo_sqlite depending on your choice of database. You may also check the available drivers with the static method PDO::getAvailableDrivers().

<?php
foreach(PDO::getAvailableDrivers() as $driver)
{
echo $driver.'<br />';
}
?>

To enable PDO simply configure --enable-pdo and --with-pdo_sqlite --with_pdo_mysql or whatever database needs supporting by PDO.

Windows users will need to un-comment the appropriate line in php.ini and restart the web server.
Where do I begin?

If you are reading this you are more than likely to have connected to a database using PHP before using a database specific function such as mysql_connect() or pg_connect or, for the truely evolved coder, SQLite. To use PDO with your database you need to have the correct PDO driver installed for it. For the SQLite PDO driver you need to configure PHP --with-pdo-sqlite. If you are using a RPM based system there are pdo-sqlite.rpm's available. Before we go any further, lets connect to a database and see what all the fuss is about.
Connect to a database

Every interaction with a database begins with a connection. Regardless of the database you use, you must connect first and establish a database handler. After connecting you your database of choice, much of the PDO methods are similar. This is why PDO is such a powerful and useful tool for PHP. Here we show how to connect to various databases and establish a database handler object that we can use for further interaction with the database.
Connect with PgSQL

As mentioned above, you may have previously tried to connect to a PgSQL database using pg_connect. Here we connect with PDO.
<?php
try {
$db = new PDO("pgsql:dbname=pdo;host=localhost", "username", "password" );
echo "PDO connection object created";
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

So that was a bit of a no-brainer to start with, we see the use of "new" to create the PDO object followed by the database type username and password. This should be familiar to most people who have connected to a database before using traditional methods.. As we have used try{} and catch(){} we see upon failure that an exception is thrown with the error message "could not find driver". This tells us the PDO_PGSQL driver is not present and needs to be loaded. As noted, an exception is thrown. PDO can handle errors in several ways, more on this later.
How did it connect to the database?
The database connection is handled internally by PDO's __construct() and this represents our database connection.

Lets see what happens if we try to connect to database as we did above without catching the exception and see what happens..
<?php
$db = new PDO("pgsql:dbname=no_database;host=localhost", "username", "password" );
?>

From the above snippet you will get a result something like this below
Fatal error: Uncaught exception 'PDOException' with message 'could not find driver' in /www/pdo.php:2 Stack trace: #0 /www/pdo.php(2): PDO->__construct('pgsql:dbname=pd...', 'username', 'password') #1 {main} thrown in /www/pdo.php on line 2

This is the default behaviour when an exception is not caught, a backtrace is generated and the script is terminated. As you can see, all the information is dumped including the file path and the database username and password. It is the responsibility of the coder to catch exceptions or to deal with the errors using set_exception_handler() function to prevent this happening. More about handling errors and exceptions later.
Connect to SQLite

When PDO is used with SQLite, database creation becomes even easier. Simply specify the path to the database file and it will be loaded. If the database file does not exist, PDO will attempt to create it. Lets see how we go with the same code but change the database to SQLite.
<?php
try {
/*** connect to SQLite database ***/
$dbh = new PDO("sqlite:/path/to/database.sdb");
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Because the database path does not exist and cannot be created, an exception is thrown, the exception is caught in the catch block and the error message is displayed with $e->Message(). Now that we know how to create a database, we can create tables and INSERT some data.

Another feature of SQLite is the ability to create tables in memory. This can be amazingly helpful if you wish to create tempory databases or tables or even for development code.
<?php
try {
/*** connect to SQLite database ***/
$db = new PDO("sqlite::memory");

/*** a little message to say we did it ***/
echo 'database created in memory';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

We see above that a database is created in memory and a message is displayed to let us know. If the creation of the database failed, a PDO exception would be thrown and the script terminated at that point, passing control to the catch block.
Connect to MySQL

MySQL is the choice of many web developers and will be used as the database of choice for much of this tutorial. Here we see how to connect to a MySQL database.

<?php

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
Connect to Firebird

Often used by developers using windows, Firebird is a good database and connection is just as simple as the examples above.
<?php
try {
$dbh = new PDO("firebird:dbname=localhost:C:\Programs\Firebird\DATABASE.FDB", "SYSDBA", "masterkey");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
Connect to Informix

Informix is popular with many windows users also, this example shows how to connect to an informix database cataloged as InformixDB in odbc.ini:
<?php
try {
$dbh = new PDO("informix:DSN=InformixDB", "username", "password");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
Connect to Oracle

The Oracle database is used by many 'enterprise' companies but these days there are sleeker options. Lets see a simple connection to Oracle
<?php
try {
$dbh = new PDO("OCI:", "username", "password")
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>

This works fine for a simple Oracle connection. The oracle driver may take two optional parameters, The database name, and the character set. To connect with a database name of "accounts" and a charset of UTF-8 the following code should be used.
<?php
try {
$dbh = new PDO("OCI:dbname=accounts;charset=UTF-8", "username", "password");
}
catch (PDOException $e)
{ echo $e->getMessage(); } ?>
Connect to ODBC

There are many connections ODBC can create, here we show how to connect to a MS Access database named accounts. The specified path is c:\\accounts.mdb.
<?php
try {
$dbh = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\accounts.mdb;Uid=Admin");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
Connect to DBLIB

Once again a Windows specific database, DBLIB can be used as follows
<?php
try {
$hostname = "localhost";
$port = 10060;
$dbname = "my_database";
$username = "username";
$password = "password";

$dbh = new PDO ("dblib:host=$hostname:$port;dbname=$dbname","$username","$password");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
Connect to IBM

This example shows connecting to an IBM DB2 database named accounts
<?php
try {
$db = new PDO("ibm:DRIVER={IBM DB2 ODBC DRIVER};DATABASE=accounts; HOSTNAME=1.2.3,4;PORT=56789;PROTOCOL=TCPIP;", "username", "password");
}
catch (PDOException $e)
{
echo $e->getMessage();
}
?>
Close a Database Connection

Up to this point we have seen how to connect to a database using PDO. But of course, we also need to disconnect when we have finished. To close the connection the object needs to be destroyed so that no reference to it remains. This is normally done at the end of a script where PHP will automatically close the connection. However, the connection may be close implicitly by assigning the value of null to the object as seen below.

<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database';

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

If the database connection fails, the code to assign a null value is never called as the exception throws control to the catch block.
PDO Query

Now that we can open and close a connection to the database with PDO, we can make use of it for what databases are made for, storing and retrieving information. The simplest form of query is the PDO query method. As the name suggests, this is used to perform database queries. Before we begin to query a database, lets create a small database with a table for animals. This will be a MySQL database for use throughout much of this tutorial. Remember, because PDO provides a common set of tools for databases, once we have the correct connection, the rest of the code is the same, regardless of the database you choose. When using PDO to query a database, the function used to do so depends on the statement you wish to send to the database. Below we will see three queries on how to INSERT, SELECT and UPDATE.
INSERT

To gather information from a database, we first need to put some info into it. We use the same code from above to connect and disconnect from the database and the INSERT query is accomplished using the PDO::exec method.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** INSERT data ***/
$count = $dbh->exec("INSERT INTO animals(animal_type, animal_name) VALUES ('kiwi', 'troy')");

/*** echo the number of affected rows ***/
echo $count;

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The output of the script above will look like this:
Connected to database
1

This shows us that we connected successfully to the database and then we have displayed the number of affected rows. PDO::exec returns the number of affected rows if successful, or zero (0) if no rows are affected. This may cause issues if you are checking for a boolean value and why it is recommended using === when to check for type also, as zero (0) may evaluate to boolean FALSE.

The PDO::exec method should be used for SQL statements that do not return a result set. We could use this same method to INSERT many more animals to our database, but a more effecient method would be to use a transaction. This is covered in the section on Transactions.
SELECT

Unlike PDO::exec the PDO::query method returns a result set, that is, a group of information from the database in the form of a PDOStatement object. Our database should look a little like the example in the What is PDO section. Using this we can SELECT information.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";
foreach ($dbh->query($sql) as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

From the script above, we can expect the results to look like this:
Connected to database
emu - bruce
funnel web - bruce
lizard - bruce
dingo - bruce
kangaroo - bruce
wallaby - bruce
wombat - bruce
koala - bruce
kiwi - troy

You will have noticed that we can iterate over the result set directly with foreach. This is because internally the PDO statement implements the SPL traversble iterator, thus giving all the benifits of using SPL. For more on SPL refer to the Introduction to SPL page. The greatest benifit of this is that SPL iterators know only one element at a time and thus large result sets become manageable without hogging memory.
UPDATE

To update a field in a database with PDO we once again use the PDO::exec method in the same manner as we did with the INSERT
<?php

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** INSERT data ***/
$count = $dbh->exec("UPDATE animals SET animal_name='bruce' WHERE animal_name='troy'");

/*** echo the number of affected rows ***/
echo $count;

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Once again we see that the connection is made to the database and one row is affected as now the kiwi has become a true Australian like the rest of the creatures. PDO::exec should be used for all database queries where no result set is required.
FETCH Modes

The section above showed how using PDO::query we can fetch information from the database. The PDO::query method returns a PDOStatement object that can be utilized in much the same was as mysql_fetch_object() or pg_fetch_object(). Of course there are times when an numerical index is needed or an associative index. PDO::query provides for this also by allowing the coder to set the fetch mode for via the PDOStatement object or via PDOStatement::setFetchMode().
FETCH ASSOC

To fetch an associative array from our results the constant PDO::FETCH_ASSOC is used and returns the column names as indexes or keys of the resulting array.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** echo number of columns ***/
$result = $stmt->fetch(PDO::FETCH_ASSOC);

/*** loop over the object directly ***/
foreach($result as $key=>$val)
{
echo $key.' - '.$val.'<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code will give a result like this:
Connected to database
animal_id - 1
animal_type - emu
animal_name - bruce

PDO has returned the results as a PDOStatement object that we can iterate over directly. The resulting indexes are the names of the fields within the animals database.
FETCH NUM

Like PDO::FETCH_ASSOC, the PDO::FETCH_NUM produces a numerical index of the result set rather than the field names.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** echo number of columns ***/
$result = $stmt->fetch(PDO::FETCH_NUM);

/*** loop over the object directly ***/
foreach($result as $key=>$val)
{
echo $key.' - '.$val.'<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code will give a result like this:
Connected to database
0 - 1
1 - emu
2 - bruce

As you can see above the indexes are now numeric in the result set
FETCH BOTH

There may be times you need to fetch both numerical and associative indexes. PDO::FETCH_BOTH produces a numerical and associative index of the result set so you can use either, or both.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** echo number of columns ***/
$result = $stmt->fetch(PDO::FETCH_BOTH);

/*** loop over the object directly ***/
foreach($result as $key=>$val)
{
echo $key.' - '.$val.'<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now we see the results have included both indexes.
Connected to database
animal_id - 1
0 - 1
animal_type - emu
1 - emu
animal_name - bruce
2 - bruce
FETCH OBJECT

This little gem takes the result set and returns it as an anonymous object or stdClass and maps the field names from the database as object properties with the values the values of stored in the database.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** echo number of columns ***/
$obj = $stmt->fetch(PDO::FETCH_OBJ);

/*** loop over the object directly ***/
echo $obj->animal_id.'<br />';
echo $obj->animal_type.'<br />';
echo $obj->animal_name;

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code gives the results like this:
Connected to database
1
emu
bruce

The use of the field names as class properties makes integrating results into an Object Oriented envioronment simple.
FETCH LAZY

PDO::FETCH_LAZY is odd as it combines PDO::FETCH_BOTH and PDO::FETCH_OBJ. I am unsure why you would want to do this, but it must have been important enough for somebody to create it. The code below is that of PDO::FETCH_BOTH and is reproduced here for examples sake.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** echo number of columns ***/
$result = $stmt->fetch(PDO::FETCH_BOTH);

/*** loop over the object directly ***/
foreach($result as $key=>$val)
{
echo $key.' - '.$val.'<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code will give a result the same as that of PDO::FETCH_BOTH. Genius!
FETCH CLASS

PDO::FETCH_CLASS instantiates a new instance of the specified class. The field names are mapped to properties (variables) within the class called. This saves quite a bit of code and speed is enhanced as the mappings are dealt with internally.
<?php
class animals{

public $animal_id;

public $animal_type;

public $animal_name;

/***
*
* @capitalize first words
*
* @access public
*
* @return string
*
*/
public function capitalizeType(){
return ucwords($this->animal_type);
}

} /*** end of class ***/

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** fetch into the animals class ***/
$obj = $stmt->fetchALL(PDO::FETCH_CLASS, 'animals');

/*** loop of the object directly ***/
foreach($obj as $animals)
{
/*** call the capitalizeType method ***/
echo $animals->capitalizeType().'<br />';
}
/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The code above produces a list of animal types, with the first letter capitalized like this:
Connected to database
Emu
Funnel Web
Lizard
Dingo
Kangaroo
Wallaby
Wombat
Koala
Kiwi

The PDO::FETCH_CLASS constant has fetched the results directly into the animals class where we were able to directly manipulate the results, nifty.

PDO provides an alternative to PDO::fetch and PDO::FETCH_CLASS. PDOStatement::fetchObject() will bundle them together to give the same result as shown here.
<?php
class animals{

public $animal_id;

public $animal_type;

public $animal_name;

/***
*
* @capitalize first words
*
* @access public
*
* @return string
*
*/
public function capitalizeType(){
return ucwords($this->animal_type);
}

} /*** end of class ***/

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** fetch into the animals class ***/
$animals = $stmt->fetchObject('animals');

/*** echo the class properties ***/
echo $animals->animal_id.'<br />';
echo $animals->capitalizeType().'<br />';
echo $animals->animal_name;

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code gives the results like this:
Connected to database
1
Emu
bruce

Note that we have called the animals::capitalizeType() method to show that we are in fact working with an instance of the animals class. PDO::fetchObject() will also work as a substitute for PDO::FETCH_OBJ.
FETCH INTO

The PDO::FETCH_INTO constant allows us to fetch the data into an existing instance of a class. Like PDO::FETCH_CLASS the field names are mapped to the class properties. With this in mind, we should be able to replicate the behaviour of PDO::FETCH_CLASS by instantiating the new object when setting the fetch mode. In this instance, the fetch mode is set using PDO::setFetchMode() method.
<?php
class animals{

public $animal_id;

public $animal_type;

public $animal_name;


public function capitalizeType(){
return ucwords($this->animal_type);
}

} /*** end of class ***/

/*** instantiate a new animals instance ***/
$animals = new animals;

$animals->animal_id = 10;

$animals->animal_type = 'crocodile';

$animals->animal_name = 'bruce';

/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM animals";

/*** fetch into an PDOStatement object ***/
$stmt = $dbh->query($sql);

/*** set the fetch mode with PDO::setFetchMode() ***/
$stmt->setFetchMode(PDO::FETCH_INTO, new animals);

/*** loop over the PDOStatement directly ***/
foreach($stmt as $animals)
{
echo $animals->capitalizeType().'<br />';
}
/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Once again, the above code produces a list of animal types, with the first letter capitalized like this:
Connected to database
Emu
Funnel Web
Lizard
Dingo
Kangaroo
Wallaby
Wombat
Koala
Kiwi
Error Handling

PDO error handling is comes in several flavours. Previously in this tutorial we have have only used the simplest of try{} catch(){} blocks to catch an error in the database connection, but what of other errors? perhaps a field name does not exist? Lets see how we go with a simple error with the previous code.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** The SQL SELECT statement with incorrect fieldname ***/
$sql = "SELECT username FROM animals";

foreach ($dbh->query($sql) as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above script will produce an error such as this:
Connected to database

Warning: Invalid argument supplied for foreach() in /www/pdo.php on line 18

This is because there is no error handling. The SELECT statement has a field name 'username' which does not exist and an error is generated by the database. The only default error handling is done with the initial connection. Unless we deal with the error, we have a problem with displaying full path to the world. To deal with this we need to set an attribute to the type of error handling we wish to utilize. The types of error handling are
Exception
Warning
Silent
Lets begin with exception as we have the try{} catch(){} blocks in place already.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** The SQL SELECT statement ***/
$sql = "SELECT username FROM animals";
foreach ($dbh->query($sql) as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now with the error mode set to Exception the error generated looks like this:
Connected to database
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'username' in 'field list'

Normally we would not show this type of error to the end user, and the exception would be handled perhaps with message saying No Results Found or something vague, but this does show how we can set the error mode as we wish. To set the error mode to Warning should look easy from here.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

/*** The SQL SELECT statement ***/
$sql = "SELECT username FROM animals";
foreach ($dbh->query($sql) as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now a different error is displayed.
Connected to database

Warning: PDO::query() [function.PDO-query]: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'username' in 'field list' in /www/pdo.php on line 21

Warning: Invalid argument supplied for foreach() in /www/pdo.php on line 21

Here and E_WARNING has been generated and if display_errors is on the error would be seen by an end user. It is hoped that if you are in a production environment this is not the case.

Lastly, there is the Silent mode. As the name suggests, this mode silences the errors so no output is sent from the error. However, it does not stop the code at the point of error and any further errors are still sent.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);

/*** The SQL SELECT statement ***/
$sql = "SELECT username FROM animals";
foreach ($dbh->query($sql) as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now we see the script above produces the following output.
Connected to database

Warning: Invalid argument supplied for foreach() in /www/pdo.php on line 21

As you can see, the error has been silenced, but the following error has not been attended to, and would need further checks to ensure the value passed to the foreach is a valid arguement.

As we saw with the exception code, the SQLSTATE code was part of the error message. This error code is also available with the PDO::errorCode() method.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';
}
catch(PDOException $e)
{
echo $e->getMessage();
}

/*** an invalide fieldname ***/
$sql = "SELECT username FROM animals";

/*** run the query ***/
$result = $dbh->query($sql);

/*** show the error code ***/
echo $dbh->errorCode();
?>

The code above shows the error code relevant to the SQLSTATE. This is a five character string as defined by the ANSI SQL standard.
Connected to database
42S22

Further information about an error may be gained from the PDO::errorInfo() method. This returns an array containing the SQLSTATE, the error code, and the error message.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';
}
catch(PDOException $e)
{
echo $e->getMessage();
}
/*** an invalid table name ***/
$sql = "SELECT animal_id FROM users";

/*** run the query ***/
$result = $dbh->query($sql);

/*** show the error info ***/
foreach($dbh->errorInfo() as $error)
{
echo $error.'<br />';
}
?>

With this code, the error information looks like this:
Connected to database
42S02
1146
Table 'animals.users' doesn't exist

If there is no error, the SQLSTATE will be the only value shown, with a value of 00000.
Prepared statements

What is a prepared statement? A prepared statement is a pre-compiled SQL statement that accepts zero or more named parameters. Ok, so thats my attempt at describing what it is, if you have a better description, let us know.

The SQL is prepared for execution. This is especially useful when using the same statement or query multiple times with different parameters, or field values. The boost in speed is hidden from userland code as the PDO driver allows client and server side caching of the query and meta data. It also helps prevent SQL injection by calling the PDO::quote() method internally.

PDO accepts two kinds of parameter markers.
named - :name
question mark - ?
You must choose one or the other, they cannot be mixed.

Lets dive in and have a look at how PDO::prepare and PDOStatement::execute work together.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** some variables ***/
$animal_id = 6;

$animal_name = 'bruce';

/*** prepare the SQL statement ***/
$stmt = $dbh->prepare("SELECT * FROM animals WHERE animal_id = :animal_id AND animal_name = :animal_name");

/*** bind the paramaters ***/
$stmt->bindParam(':animal_id', $animal_id, PDO::PARAM_INT);
$stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);

/*** execute the prepared statement ***/
$stmt->execute();

/*** fetch the results ***/
$result = $stmt->fetchAll();

/*** loop of the results ***/
foreach($result as $row)
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'];
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code will produce the following:
Connected to database
6
wallaby
bruce

Errr, what was that?
What is this name = :variable business
What we have done is bind the variable named $animal_id and $animal_name to the statement. Remember this as many find it difficult to grasp. You are not binding the value of the variable, you are binding the variable itself. Lets change the value of the animal_id after the variable is bound and see what happens..
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** some variables ***/
$animal_id = 6;

$animal_name = 'bruce';

/*** prepare the SQL statement ***/
$stmt = $dbh->prepare("SELECT * FROM animals WHERE animal_id = :animal_id AND animal_name = :animal_name");

/*** bind the paramaters ***/
$stmt->bindParam(':animal_id', $animal_id, PDO::PARAM_INT);
$stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);

/*** reassign the animal_id ***/
$animal_id = 3;

/*** execute the prepared statement ***/
$stmt->execute();

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'];
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now see the results have changed
Connected to database
3
lizard
bruce

Because we have bound the variable $animal_id to the $stmt object any change to the value of that varible will be reflected in the statement. This format can be used for both SELECT and INSERT statements. But this is a bit cumbersome for a single query and the above PDO query could have done the job equally as well, so lets run the query multiple times. Ssimply by changing the animal_id and animal_name variables we can run the query over and over without re-writing as it is already 'prepared'.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** some variables ***/
$animal_id = 6;
$animal_name = 'bruce';

/*** prepare the SQL statement ***/
$stmt = $dbh->prepare("SELECT * FROM animals WHERE animal_id = :animal_id AND animal_name = :animal_name");

/*** bind the paramaters ***/
$stmt->bindParam(':animal_id', $animal_id, PDO::PARAM_INT);
$stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);

/*** reassign the animal_id ***/
$animal_id = 3;
$animal_name = 'kevin';

/*** execute the prepared statement ***/
$stmt->execute();

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'].'<br />';
}

/*** reassign the animal_id ***/
$animal_id = 7;
$animal_name = 'bruce';

/*** execute the prepared statement ***/
$stmt->execute();

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'].'<br />';
}

/*** reassign the animal_id ***/
$animal_id = 4;
/*** execute the prepared statement ***/
$stmt->execute();

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'];
}

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

Now we have run the query 3 times using the same prepared statement. The results look like this:
Connected to database
7
wombat
bruce
4
dingo
bruce

The second result set is missing as there is no animal named \'kevin\', all Australians are named \'bruce\'. Note also in the above code we have changed the loop from foreach and PDOStatement::fetchAll() to a while loop using PDOStatement::fetch()As has been mentioned we can run this over and over, but while it is shorter than coding the query over and over, we can also use an array of values!
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** some variables ***/
$data = array('animal_id'=>6, 'animal_name'=>'bruce');

/*** prepare the SQL statement ***/
$stmt = $dbh->prepare("SELECT * FROM animals WHERE animal_id = :animal_id AND animal_name = :animal_name");

/*** bind the paramaters ***/
$stmt->bindParam(':animal_id', $animal_id, PDO::PARAM_INT);
$stmt->bindParam(':animal_name', $animal_name, PDO::PARAM_STR, 5);

/*** reassign the variables ***/
$data = array('animal_id'=>3, 'animal_name' => 'bruce');

/*** execute the prepared statement ***/
$stmt->execute($data);

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'].'<br />';
}

/*** reassign the variables again ***/
$data = array('animal_id'=>4, 'animal_name' => 'bruce');

/*** execute the prepared statement ***/
$stmt->execute($data);

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'].'<br />';
}

/*** reassign the variables ***/
$data = array('animal_id'=>9, 'animal_name' => 'bruce');

/*** execute the prepared statement ***/
$stmt->execute($data);

/*** loop over the results ***/
while($row = $stmt->fetch())
{
echo $row['animal_id'].'<br />';
echo $row['animal_type'].'<br />';
echo $row['animal_name'];
}


/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
Transactions

At the beginning of this tutorial was saw multiple INSERT statements to set up the initial database. This works fine but is code intensive and with a database like SQLite a problem arises with file locking for each access. The process can be bundled into a single access by using a transaction. Transactions are quite simple and have the benifit of rolling back changes should an error occur, perhaps a system crash.

A PDO transaction begins with the with PDO::beginTransaction() method. This method turns off auto-commit and any database statements or queries are not committed to the database until the transaction is committed with PDO::commit. When PDO::commit is called, all statements/queries are enacted and the database connection is returned to auto-commit mode.

This example shows how we might set up the animals database used in this tutorial.
<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

/*** database name ***/
$dbname = 'animals';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the PDO error mode to exception ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*** begin the transaction ***/
$dbh->beginTransaction();

/*** CREATE table statements ***/
$table = "CREATE TABLE animals ( animal_id MEDIUMINT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
animal_type VARCHAR(25) NOT NULL,
animal_name VARCHAR(25) NOT NULL
)";
$dbh->exec($table);
/*** INSERT statements ***/
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('emu', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('funnel web', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('lizard', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('dingo', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('kangaroo', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('wallaby', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('wombat', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('koala', 'bruce')");
$dbh->exec("INSERT INTO animals (animal_type, animal_name) VALUES ('kiwi', 'bruce')");

/*** commit the transaction ***/
$dbh->commit();

/*** echo a message to say the database was created ***/
echo 'Data entered successfully<br />';
}
catch(PDOException $e)
{
/*** roll back the transaction if we fail ***/
$dbh->rollback();

/*** echo the sql statement and error message ***/
echo $sql . '<br />' . $e->getMessage();
}
?>
Get Last Insert Id

This is a common task required when you need to get the id of the last INSERT. This is done with PDO::lastInserId() method as shown here.

<?php
/*** mysql hostname ***/
$hostname = 'localhost';

/*** mysql username ***/
$username = 'username';

/*** mysql password ***/
$password = 'password';

try {
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';

/*** set the error reporting attribute ***/
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*** INSERT a new row ***/
$dbh->exec("INSERT INTO animals(animal_type, animal_name) VALUES ('galah', 'polly')");

/*** display the id of the last INSERT ***/
echo $dbh->lastInsertId();

/*** close the database connection ***/
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
A Global Instance

Ever need a global instance of your database connection? Here we achieve this with the use of the Singleton design patern. The goal of a singleton is to ensure the class has only a single instance and provide a global point of access to it. Here we use the getInstance() method to achieve this. A new instance is only created the first time it is accessed and all subsequent accesses are simply returned the existing instance.

<?php
class db{

/*** Declare instance ***/
private static $instance = NULL;

/**
*
* the constructor is set to private so
* so nobody can create a new instance using new
*
*/
private function __construct() {
/*** maybe set the db name here later ***/
}

/**
*
* Return DB instance or create intitial connection
*
* @return object (PDO)
*
* @access public
*
*/
public static function getInstance() {

if (!self::$instance)
{
self::$instance = new PDO("mysql:host='localhost';dbname='animals'", 'username', 'password');;
self::$instance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$instance;
}

/**
*
* Like the constructor, we make __clone private
* so nobody can clone the instance
*
*/
private function __clone(){
}

} /*** end of class ***/

try {
/*** query the database ***/
$result = DB::getInstance()->query("SELECT * FROM animals");

/*** loop over the results ***/
foreach($result as $row)
{
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>

The above code will produce a result like this:
emu - bruce
funnel web - bruce
lizard - bruce
dingo - bruce
kangaroo - bruce
wallaby - bruce
wombat - bruce
koala - bruce

This method of access saves the overhead created when a new instance of an object is called each time it is referenced, so you have have few references to it. Also, if you wish to pass the objects state from one reference to another there is no need to create from the initial state.

Note that the constructor and clone methods have been made private to ensure that an instance of the class cannot be instantiated or cloned.
Conclusions.

If you have got this far you will have seen how to create a connection, prepare a statement and exceute, and to bind Params using bindParam(). This is what most folks will be using to begin with and shows the effectiveness of using PDO to make code more portable. We highly recommend you visit http://www.php.net/manual/en/ref.pdo.php and read up on all that PDO has to offer.