Why you Should be using PHP’s PDO for Database Access

Why you Should be using PHP’s PDO for Database Access

Tutorial Details
  • Technology: PHP
  • Difficulty: Moderate
  • Estimated Completion Time: 40 Minutes

Many PHP programmers learned how to access databases by using either the MySQL or MySQLi extensions. As of PHP 5.1, there’s a better way. PHP Data Objects (PDO) provide methods for prepared statements and working with objects that will make you far more productive!

Republished Tutorial

Every few weeks, we revisit some of our reader's favorite posts from throughout the history of the site. This tutorial was first published in May of 2010.


PDO Introduction

“PDO – PHP Data Objects – is a database access layer providing a uniform method of access to multiple databases.”

It doesn’t account for database-specific syntax, but can allow for the process of switching databases and platforms to be fairly painless, simply by switching the connection string in many instances.

PDO - db abstraction layer

This tutorial isn’t meant to be a complete how-to on SQL. It’s written primarily for people currently using the mysql or mysqli extension to help them make the jump to the more portable and powerful PDO.

Database Support

The extension can support any database that a PDO driver has been written for. At the time of this writing, the following database drivers are available:

  • PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
  • PDO_FIREBIRD ( Firebird/Interbase 6 )
  • PDO_IBM ( IBM DB2 )
  • PDO_INFORMIX ( IBM Informix Dynamic Server )
  • PDO_MYSQL ( MySQL 3.x/4.x/5.x )
  • PDO_OCI ( Oracle Call Interface )
  • PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
  • PDO_PGSQL ( PostgreSQL )
  • PDO_SQLITE ( SQLite 3 and SQLite 2 )
  • PDO_4D ( 4D )

All of these drivers are not necessarily available on your system; here’s a quick way to find out which drivers you have:

print_r(PDO::getAvailableDrivers());

Connecting

Different databases may have slightly different connection methods. Below, the method to connect to some of the most popular databases are shown. You’ll notice that the first three are identical, other then the database type – and then SQLite has its own syntax.

Connection String
try {
  # MS SQL Server and Sybase with PDO_DBLIB
  $DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
  $DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");

  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

  # SQLite Database
  $DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
    echo $e->getMessage();
}

Please take note of the try/catch block – you should always wrap your PDO operations in a try/catch, and use the exception mechanism – more on this shortly. Typically you’re only going to make a single connection – there are several listed to show you the syntax. $DBH stands for ‘database handle’ and will be used throughout this tutorial.

You can close any connection by setting the handle to null.

# close the connection
$DBH = null;

You can get more information on database specific options and/or connection strings for other databases from PHP.net.


Exceptions and PDO

PDO can use exceptions to handle errors, which means anything you do with PDO should be wrapped in a try/catch block. You can force PDO into one of three error modes by setting the error mode attribute on your newly created database handle. Here’s the syntax:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

No matter what error mode you set, an error connecting will always produce an exception, and creating a connection should always be contained in a try/catch block.

PDO::ERRMODE_SILENT

This is the default error mode. If you leave it in this mode, you’ll have to check for errors in the way you’re probably used to if you used the mysql or mysqli extensions. The other two methods are more ideal for DRY programming.

PDO::ERRMODE_WARNING

This mode will issue a standard PHP warning, and allow the program to continue execution. It’s useful for debugging.

PDO::ERRMODE_EXCEPTION

This is the mode you should want in most situations. It fires an exception, allowing you to handle errors gracefully and hide data that might help someone exploit your system. Here’s an example of taking advantage of exceptions:

# connect to the database
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

  # UH-OH! Typed DELECT instead of SELECT!
  $DBH->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "I'm sorry, Dave. I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

There’s an intentional error in the select statement; this will cause an exception. The exception sends the details of the error to a log file, and displays a friendly (or not so friendly) message to the user.


Insert and Update

Inserting new data, or updating existing data is one of the more common database operations. Using PDO, this is normally a two-step process. Everything covered in this section applies equally to both UPDATE and INSERT operations.

2 to 3 step insert and update

Here’s an example of the most basic type of insert:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
$STH->execute();

You could also accomplish the same operation by using the exec() method, with one less call. In most situations, you’re going to use the longer method so you can take advantage of prepared statements. Even if you’re only going to use it once, using prepared statements will help protect you from SQL injection attacks.

Prepared Statements

Using prepared statements will help protect you from SQL injection.

A prepared statement is a precompiled SQL statement that can be executed multiple times by sending just the data to the server. It has the added advantage of automatically making the data used in the placeholders safe from SQL injection attacks.

You use a prepared statement by including placeholders in your SQL. Here’s three examples: one without placeholders, one with unnamed placeholders, and one with named placeholders.

# no placeholders - ripe for SQL Injection!
$STH = $DBH->("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");

# unnamed placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);

# named placeholders
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");

You want to avoid the first method; it’s here for comparison. The choice of using named or unnamed placeholders will affect how you set data for those statements.

Unnamed Placeholders

# assign variables to each place holder, indexed 1-3
$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);

# insert one row
$name = "Daniel"
$addr = "1 Wicked Way";
$city = "Arlington Heights";
$STH->execute();

# insert another row with different values
$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();

There are two steps here. First, we assign variables to the various placeholders (lines 2-4). Then, we assign values to those placeholders and execute the statement. To send another set of data, just change the values of those variables and execute the statement again.

Does this seem a bit unwieldy for statements with a lot of parameters? It is. However, if your data is stored in an array, there’s an easy shortcut:

# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');

$STH = $DBH->("INSERT INTO folks (name, addr, city) values (?, ?, ?);
$STH->execute($data);

That’s easy!

The data in the array applies to the placeholders in order. $data[0] goes into the first placeholder, $data[1] the second, etc. However, if your array indexes are not in order, this won’t work properly, and you’ll need to re-index the array.

Named Placeholders

You could probably guess the syntax, but here’s an example:

# the first argument is the named placeholder name - notice named
# placeholders always start with a colon.
$STH->bindParam(':name', $name);

You can use a shortcut here as well, but it works with associative arrays. Here’s an example:

# the data we want to insert
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );

# the shortcut!
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);

The keys of your array do not need to start with a colon, but otherwise need to match the named placeholders. If you have an array of arrays you can iterate over them, and simply call the execute with each array of data.

Another nice feature of named placeholders is the ability to insert objects directly into your database, assuming the properties match the named fields. Here’s an example object, and how you’d perform your insert:

# a simple object
class person {
    public $name;
    public $addr;
    public $city;

    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}

$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');

# here's the fun part:
$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);

By casting the object to an array in the execute, the properties are treated as array keys.


Selecting Data

Fetch data into arrays or objects

Data is obtained via the ->fetch(), a method of your statement handle. Before calling fetch, it’s best to tell PDO how you’d like the data to be fetched. You have the following options:

  • PDO::FETCH_ASSOC: returns an array indexed by column name
  • PDO::FETCH_BOTH (default): returns an array indexed by both column name and number
  • PDO::FETCH_BOUND: Assigns the values of your columns to the variables set with the ->bindColumn() method
  • PDO::FETCH_CLASS: Assigns the values of your columns to properties of the named class. It will create the properties if matching properties do not exist
  • PDO::FETCH_INTO: Updates an existing instance of the named class
  • PDO::FETCH_LAZY: Combines PDO::FETCH_BOTH/PDO::FETCH_OBJ, creating the object variable names as they are used
  • PDO::FETCH_NUM: returns an array indexed by column number
  • PDO::FETCH_OBJ: returns an anonymous object with property names that correspond to the column names

In reality, there are three which will cover most situations: FETCH_ASSOC, FETCH_CLASS, and FETCH_OBJ. In order to set the fetch method, the following syntax is used:

$STH->setFetchMode(PDO::FETCH_ASSOC);

You can also set the fetch type directly within the ->fetch() method call.

FETCH_ASSOC

This fetch type creates an associative array, indexed by column name. This should be quite familiar to anyone who has used the mysql/mysqli extensions. Here’s an example of selecting data with this method:

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);

while($row = $STH->fetch()) {
    echo $row['name'] . "\n";
    echo $row['addr'] . "\n";
    echo $row['city'] . "\n";
}

The while loop will continue to go through the result set one row at a time until complete.

FETCH_OBJ

This fetch type creates an object of std class for each row of fetched data. Here’s an example:

# creating the statement
$STH = $DBH->query('SELECT name, addr, city from folks');

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);

# showing the results
while($row = $STH->fetch()) {
    echo $row->name . "\n";
    echo $row->addr . "\n";
    echo $row->city . "\n";
}

FETCH_CLASS

The properties of your object are set BEFORE the constructor is called. This is important.

This fetch method allows you to fetch data directly into a class of your choosing. When you use FETCH_CLASS, the properties of your object are set BEFORE the constructor is called. Read that again, it’s important. If properties matching the column names don’t exist, those properties will be created (as public) for you.

This means if your data needs any transformation after it comes out of the database, it can be done automatically by your object as each object is created.

As an example, imagine a situation where the address needs to be partially obscured for each record. We could do this by operating on that property in the constructor. Here’s an example:

class secret_person {
    public $name;
    public $addr;
    public $city;
    public $other_data;

    function __construct($other = '') {
        $this->address = preg_replace('/[a-z]/', 'x', $this->address);
        $this->other_data = $other;
    }
}

As data is fetched into this class, the address has all its lowercase a-z letters replaced by the letter x. Now, using the class and having that data transform occur is completely transparent:

$STH = $DBH->query('SELECT name, addr, city from folks');
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');

while($obj = $STH->fetch()) {
    echo $obj->addr;
}

If the address was ’5 Rosebud,’ you’d see ’5 Rxxxxxx’ as your output. Of course, there may be situations where you want the constructor called before the data is assigned. PDO has you covered for this, too.

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');

Now, when you repeat the previous example with this fetch mode (PDO::FETCH_PROPS_LATE) the address will NOT be obscured, since the constructor was called and the properties were assigned.

Finally, if you really need to, you can pass arguments to the constructor when fetching data into objects with PDO:

$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

If you need to pass different data to the constructor for each object, you can set the fetch mode inside the fetch method:

$i = 0;
while($rowObj =  $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) {
    // do stuff
    $i++
}

Some Other Helpful Methods

While this isn’t meant to cover everything in PDO (it’s a huge extension!) there are a few more methods you’ll want to know in order to do basic things with PDO.

$DBH->lastInsertId();

The ->lastInsertId() method is always called on the database handle, not statement handle, and will return the auto incremented id of the last inserted row by that connection.

$DBH->exec('DELETE FROM folks WHERE 1');
$DBH->exec("SET time_zone = '-8:00'");

The ->exec() method is used for operations that can not return data other then the affected rows. The above are two examples of using the exec method.

$safe = $DBH->quote($unsafe);

The ->quote() method quotes strings so they are safe to use in queries. This is your fallback if you’re not using prepared statements.

$rows_affected = $STH->rowCount();

The ->rowCount() method returns an integer indicating the number of rows affected by an operation. In at least one known version of PDO, according to [this bug report](http://bugs.php.net/40822) the method does not work with select statements. If you’re having this problem, and can’t upgrade PHP, you could get the number of rows with the following:

$sql = "SELECT COUNT(*) FROM folks";
if ($STH = $DBH->query($sql)) {
    # check the row count
    if ($STH->fetchColumn() > 0) {

    # issue a real select here, because there's data!
    }
    else {
        echo "No rows matched the query.";
    }
}

Conclusion

I hope this helps some of you migrate away from the mysql and mysqli extensions. What do you think? Are there any of you out there who might make the switch?

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.stewartdoxey.co.uk Stewart

    Excellent, I’ve been looking into php mysqli extensions lately as an alternative to mysql but didn’t consider PDO (until now!).

    Thanks for the post!

  • http://www.scottcorgan.com Scott Corgan

    It’s features like this that enterprise and .NET developers overlook. PHP has the reputation of being the well-liked, irresponsible little brother programing language. But, people often overlook the new and current features that PHP offers to make it easier and scalable to developers.

    Great post!

  • http://philip@philipdamra.com djheru

    Nice tutorial. Many beginners start out using the mysql extension because that’s what is covered in most tutorials. Information like this allows new PHP coders to incorporate best practices earlier.

  • http://www.mikhailkozlov.com Mikhail

    Great write up. It is time for new CRUD class for me.

  • http://josephscott.org/ Joseph Scott

    It doesn’t account for database-specific syntax, but can allow for the process of switching databases and platforms to be fairly painless, simply by switching the connection string in many instances.

    The first part of that sentence is true and as a result makes the second half of the sentence false. Switching databases, except in the most trivial and basic cases, is not as easy as switching a connection string.

    That said, having a common API for talking to different databases is handy, even if it doesn’t solve all your problems.

    I also didn’t see any discussion in the prepared statements section about performance concerns. For DBs that support real prepared statements PDO makes twice as many DB requests, since it sends the proposed prepared statement first to make sure it is legit and then sends the data. There are cases where prepared statements can still be a win from the performance perspective, but knowing the difference is important.

    lastInsertId() also supports sequences for those using database (like Oracle and PostgreSQL) that implement them.

    • Erik

      It means you have to check your SQL statements for database specific syntax – ie. mySQL’s LIMIT vs SQL Servers TOP – but that’s less extensive then having to rewrite everything. I just moved a fairly complex DB application from SQLite to mySQL at a client’s request, and since the DB access was with PDO, it took very little time.

    • Nicolay

      Then ADODB is much better.

      It accounts for database-specific syntax, and database-specific features.

      In fact, this article should have been about ADODB.

  • http://www.avey.de Way

    Nice and clean overview and very good instructions. Everybody should use pdo since it’s so handy and powerful.
    I can only recommend to learn and use to the advantages of prepared statements and the hole concept of pdo, it’s worth!

  • Russell Skaggs

    Thanks! Been looking for a good PDO tutorial.

  • Hitesh Chavda

    Very well explained. good for people who want to use PDO.
    Thanks.

  • http://www.medokin.de Nikodem Jaworski

    I am sure that it is a good way to deal with large projects, but in my opinion it is too complex for conventional sites.
    In many examples you can save just a few lines in contrast to mysqli.

    I must say that the article is well summarized and i think to try it, but surely at first just for fun.

  • James

    Excellent!

    I have been using the PDO class for a while and I love it, although it took some time getting used to.

    Great tutorial, it helped me with some stuff too.

    Thanks!

  • http://matt-bridges.com/ Matt Bridges

    This is excellent! I will definitely have to come back and look into trying PDO from now on. It certainly seems a little more straightforward and flexible than mysql or mysqli. Great post!

  • Dominik

    Good tutorial and I agree with the using of PDOs.
    But if you are serious of getting into PHP and database related topics, I would suggest the use of a ORM – DOctrine to be precise. It allows not only a more object-oriented way of doing things but has many advanced features.

    It IS important to know what’s going on in the background (namely PDOs in Doctrines case) but I would never exchange Doctrine for PDO or even worse, pure SQL. Even if performance is critical in an application, the possible performance drop produced by Doctrine (especially Doctrine 2 with its PHP 5.3 code, which is even lower compared to 5.2 in terms of speed) can be ignored in favor of the advantages it brings.

  • http://brettic.us Bretticus

    Thanks. Was not aware of the FETCH_CLASS capability. I can see that would be useful for your library of strictly defined entity classes.

    If new programmers used PDO’s prepared statements alone, we could probably avoid PHP SQL injection altogether (well, do a lot better than we do now.)

    Great tut!

  • Patrick

    Sooner or later i’ll give PDO a try.

    But: I think multi-queries are fantastic. Okay, they produce a lot more code (because of it’s do-while shema), but 1 db-request vs. 10? Think it should be clear what to use. I’m writing my own CMS and combine a lot of db-requests within one. I use (at this time) only 10 to max. 15 DB-Requests for system/module-vars, user-auth, content loading and so on. This wouldn’t be able with PDO. And i just dont have to miss security functions, because i use an own “prepared statements” function for mysqli, so all variables will automatically be escaped.

    PDO is really a nice function, but not usable without multiquerying.

    • Erik

      Yes this is a possible deal breaker for some; for others, they’ll never miss it. I find the ease of use relating to prepared statements and the powerful object features make it worth while.

      • Patrick

        Yeah, that’s what i mean, i think PDO is very powerful – especially because it supports much more databases with exaclty the same class functions. That’s a really big goal. Prepared Statements are also a good thing, if you don’t want to check any sql statement “manually”.

        I really hope, that PDO will support MultiQueries in the future. As long as it don’t support it, i won’t use it for bigger projects.

  • Hydraulics

    I don’t see how PDO would work with dynamic queries

    $data = array(cleaned and validated $_POST array);

    $queries = new queries();
    $result = $queries->insertQ(‘mytable’, $data);

    // queries class

    class queries extends database
    {
    public function __construct(){}

    public function insertQ($table, &$data)
    {
    $query = “INSERT INTO $table (“.implode(‘,’,array_keys($data)).”) VALUES (‘”.implode(“‘,’”, array_values($data)).”‘)”;

    if($result = mysqli_query($db->link, $query))
    }

    }

    How is it possible to bind with this method for PDO?

    • Erik

      I’m not sure I understand your question. You’re not binding data now, you’re putting it directly in your SQL string. You’d simply create a statement with placeholders like:

      $STH = $DBH->prepare(INSERT INTO $table ( col_1, col_2, col_3 ) values ( ?, ?, ? );
      $STH->execute($data);

      Where $data is an array of the 3 values you’re inserting.

    • Patrick

      This, what you want, doesn’t work as you wish…

      The only was is to prepare the Statement with the array keys, count the keys and build a string with the placeholders for the values. such like:

      $count = count($data);
      $x = 1;
      $value_placeholder = “”;

      while($count prepare($sql);
      $sth->execute(array_values($data));

  • http://www.wype.fr Maxime

    Nice article, I’m using PDO since last year, but I wasn’t aware of all those possibilities. Thanks for sharing!

    There is a typo : “PDO::ERRMODE_SLIENT” instead of “PDO::ERRMODE_SILENT”

  • http://www.kevinbradwick.co.uk Kevin

    Good post.

    PDO is one of the many reason I have moved away from CodeIgniter as a framework.

    • Gregory

      I use CI with Doctrine and am happy with that combo for now.

  • http://ds.laroouse.com esranull

    Very well explained. good for people who want to use PDO.
    Thanks

  • http://www.escodent.de Daniel S

    Thats a great tutorial – i always looked for an PDO Tutorial – and woosh, here is it! Thanks for that, PDO is so mighty!

  • http://mario.ec/ Mario

    Just don’t use it with MS SQL Server, it truncates fields to 4kb

    • http://www.kevinbradwick.co.uk Kevin

      I’ve used it with MSSQL and never come across this problem.

    • frank

      I had this problem using php odbc but only on a mac server. It ended up being the odbc driver.

  • http://henrik.lissner.net Henrik Lissner

    I’ve been using PDO for a long time, and actually have sometimes wanted to step back and incorporate mysqli into my sites instead – but mysqli’s by-reference variable-arguments parameter binding functions make it such a hassle to wrap them into your own classes, which is usually what you want to do when it comes to making a standardized abstraction layer.

    PDO on the other hand, is much less pigheaded about just that, and adds easy named parameter support, but sacrifices multi-query support and some margin of performance.

    In the perfect world, where those syntactical flaws in mysqli are ironed out, though, I would have chosen it over PDO.

    But in our world, PDO seems the easier of the two.

  • http://zackhovatter.com Zack Hovatter

    Yet another great article. I’m definitely going to be going Premium soon :)

  • J-F Bélisle

    Nice post !
    I’ve been using MySQLi prepared statement but I’ll give PDO a try for sure.
    Thank you !

  • Andrew

    Nice, finally some useful article.
    Been coming to nettuts for past 2 weeks and leave instantly as soon i saw titles of articles.
    Cheers, Erik!

  • http://twitter.com/eantz Destiya Dian

    Thanks for the article..
    It’s useful very useful for me..
    Bookmark this for future use..

  • William

    Erik … thanks …. i love this tutorial !!!

  • http://www.twitter.com/mamunabms Abdullah Al Mamun

    Great post. Thanks a lot. Bookmarked it. :-)

  • Sk1ppeR

    You had to mention the transaction possibility but nonetheless it’s a great tutorial about PDO. Cheers

    • Erik

      I’m finding in writing these tutorials that there’s a trade off between being comprehensive and being digestible. My original outline for the article would have resulted in something nearly twice as long because there are so many nooks and crannies in PDO and SQL in general.

      Instead of trying to cover everything, I tried to cover enough for people who wanted to give PDO a try but had not yet, and I hope I accomplished that goal.

  • http://ilopezdeaudikana.com mutiu

    nice and very well explained….

  • Zaw

    WOW. it teaches me a lot. Thank u so much for the post. If u can do other php extension in future tutorial that would b fantastic. Thanks.

  • Anonymous

    Keep in mind that PDO will only HELP avoiding mysqli. It will, in NO WAY, remove mysqli from your application.

    For example:

    Let’s imagine the following situation. We are willing to use a GET/POST variable in our LIMIT/GROUP BY CLAUSE (others possible too), we are obviously using PDO statements.

    Now, if we are getting some injection like “234234 UNION ALL SELECT DISTINCT NULL, table_name, NULL, NULL FROM information_schema.columns WHERE columns.table_schema = char(X,X,X,X,X,X) — -” the mysqli will success!

    In other words, PDO is useful, but you MUST also use filters like ctype_alpha/ctype_alnum for strings (no slashes allowed) and (int) casting for integers (this will convert non integer variables to 0).

    My two cents.

    • http://www.mikematas.com MikieM

      Interesting remark you made there. Glad to see some security researchers show their faces around.. 5*****

    • John

      Won’t ctype_alnum fail if a string contains an exclamation point for example, not just on forward slashes?

  • http://www.nouveller.com/ Benjamin Reid

    Will be learning this today, If I can drag myself away from CodeIgniter!

    :P

  • Gav

    Dude! This is a fab tutorial one of the best been looking for something like this for ages! :D
    Cheers!

  • Matt

    Thanks for a great tutorial, I’ve been very stubborn in not wanting to rewrite my CRUD class from mysqli but this may just give me the push i need to switch over to PDO.

  • http://www.devlim.com devlim

    all easy to use and understand, only PDO::FETCH_CLASS a little bit hard to use.

  • guest

    I’ve know about PDO for a long time now, but wasn’t sure it might be install on the server ur goin to implement it, if your really concern with compatibility. Can anyone enlighten me about this.

    • Erik

      PDO requires PHP 5 and comes as part of the typical PHP installation on PHP 5.1 and later.

  • http://sixbytesunder.com Wojtek

    Hi
    Great article but I have to disagree with one bit at the end: “->rowCount() method (…) does not work with select”.
    That was true due to a bug in PHP 5.1.6 but for all later versions of PHP rowCount() returns a number of selected rows from a SELECT statement.
    Here’s a quick post about that bug and how to fix it http://allurcode.com/2010/03/30/pdo-rowcount-not-working-in-php-5-1-6/

    • Erik

      My apologies, and you are absolutely correct, ->rowCount() works like a charm in my dev environment (5.3) but my typical production server is a bit out of date. I’ll see if I can get Jeffrey to update the article for me!

      • http://sixbytesunder.com Wojtek

        Cool :) We don’t want to misinform people :)

  • http://www.jordanwalker.net Jordan Walker

    A cornerstone of OOP.

  • mdennisa

    veeery nice, very very nice tuts

    thanks eric!

  • Carl Welch

    My only real gripe with PDO is that it doesn’t support SSL connections to MySQL. I would encourage anyone who cares to vote on this bug:

    http://bugs.php.net/bug.php?id=48587

  • http://kodegeek.wordpress.com Musa

    Perfect. One thing – if we pass the data array on execute method rather than bindParam, what’s the problem? Isn’t this simple?

    Again, Awesome post. love it.

  • Robin

    PDO – who knew? ! Thanks for the great tutorial – this is a great solution. Write more, write more!

  • Evert Padje

    Props for the article, it covers a lot of sides of PDO.

    “It doesn’t account for database-specific syntax, but can allow for the process of switching databases and platforms to be fairly painless, simply by switching the connection string in many instances.”

    This is just nonsense. Every site has specific SQL queries that are optimized for MySQL or PostgreSQL, for instance. Have you ever switched a big site to a different database? It’s not as simple as that.

    You can say PDO is great and way better than mysql_* functions, but I definitely disagree. The mysql_* functions are still being maintained and the mysqli_* functions are okay too.

    It’s just a choice you make, so choose something you prefer and be happy with it.

  • http://cb.net.au Christian

    Great post, thanks!

  • Simon

    Nice article, thanks. Hope we’ll get more of those ;)
    But… (yeah sorry) I just hope people don’t get it wrong. PDO is great for prepared statements and for multiple database types support but that’s all. All other features are already available with standard mysql (and postgre I guess).
    So yes, it is great and developers should know how it works but I’m not sure I would recommend it as a replacement of standard querying.

  • commenter

    I was going to write such a tutorial, you beat me to it and did it better tahn I planned on doing mine :D

    PDO is great, especially prepared statements – And also provides multiple db system support.

    The main thing is if you ar ebuiling something which is meant to work on different RDBMS using PDO as the core is excellent – Obviously uo need a wrapper to deal with syntax but it saves you building a driver class for each rbdms you plan on supporting.

    The advantage of PDO are:
    1) Prepared Statements
    2) The (natural) OOP structure
    3) Mutli RDBMS support (ideal for the core of a mutli rdbms dbal [wrapper for creation syntax])

  • http://www.deluxeblogtips.com Deluxe Blog Tips

    Great. I’ve been using mysqli for a long time and have written a class for working with it more easier. The PDO built-in class seems can do it, too. No more effort. This is really nice. Thanks for sharing.

  • DanR

    Why would I want to use this instead of adodb? Are there any advantages?

  • http://piry.me/ Piry

    I didn’t really understand from your article why would PDO be a better choice.

    I do understand that you only write code *once* and it can work with several database systems, and I have worked with PDO so I’ve seen that in action.

    But I don’t find the PDO approach to be the “high performance” one. I prefer to make my own database class and use that. If i need to change the database system I’ll just replace the current database class file (database.class.mysql.php) with the new one (database.class.mssql.php).
    I’ll still use $database->query(etc); or $database->fetch_array(etc);, and can add a “query adapt” function to convert the mysql sql to mssql sql (limit -> top, etc).

    I really should do some benchmarks and see query numbers, query speeds between a PDO approach and a custom-class.
    If any of you already have and got some results, I’d be very interested to have a look at them.

  • Green

    Hello. I’m a beginner in PHP…and I’m using mysql. I tried to follow the tutorial and it worked! Thanks for making it look easy…even beginners can follow this.

    I’ve read many comments here about the advantage of PDO over mysql and mysqli. However, there is this one term I cannot understand…”Multiple-query support”, maybe I know what this is but I just don’t know how it looks like and know there’s a term for it. Can someone here provide an example of a “multiple-query” that PDO does not support. I’ve searched it in google but it doesn’t seem to be pointing me to the right direction.

    Thanks guys!