Php Data Objects


Published on

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Php Data Objects

  1. 1. PHP Data Objects A tour of new features
  2. 2. Introduction <ul><li>PHP Data Objects, (PDO) is a PHP5 extension that defines a lightweight DBMS connection abstraction library (sometimes called data access abstraction library). </li></ul><ul><li>PDO provides a data-access abstraction layer, which means that, regardless of which database you're using, you use the same functions to issue queries and fetch data. </li></ul><ul><li>This means that PDO defines a unified interface for creating and maintaining database connections, issuing queries, quoting parameters, traversing result sets, dealing with prepared statements, and error handling. </li></ul><ul><li>PDO ships with PHP 5.1, and is available as a PECL extension for PHP 5.0; PDO requires the new OO features in the core of PHP 5, and so will not run with earlier versions of PHP. </li></ul>
  3. 3. Installation Guidelines <ul><li>Windows users running PHP 5.1.0 and up </li></ul><ul><ul><ul><li>PDO and all the major drivers ship with PHP as shared extensions, and simply need to be activated by editing the php.ini file: </li></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo.dll </li></ul></ul></ul></ul><ul><ul><ul><li>Next, choose the other database-specific DLL files and enable them in php.ini below php_pdo.dll. For example: </li></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_firebird.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_mssql.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_mysql.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_oci.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_oci8.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_odbc.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_pgsql.dll </li></ul></ul></ul></ul><ul><ul><ul><ul><li>extension=php_pdo_sqlite.dll </li></ul></ul></ul></ul><ul><ul><ul><li>These DLLs should exist in the system's extension_dir. </li></ul></ul></ul>
  4. 4. Using PDO
  5. 5. Connecting to the Database <ul><li>Let's consider the well-known MySQL connection scenario: </li></ul><ul><ul><li>mysql_connect($host, $user, $password); </li></ul></ul><ul><ul><li>mysql_select_db($db); </li></ul></ul><ul><li>In SQLite , for example, we would write something like the following: </li></ul><ul><ul><li>$dbh = sqlite_open($db, 0666); </li></ul></ul><ul><li>In PostgreSQ L, for example, we would write something like the following: </li></ul><ul><ul><li>pg_connect(&quot;host=$host dbname=$db user=$user password=$password&quot;); </li></ul></ul><ul><li>Here, we establish a connection and then select the default database for the connection. (OLD /CURRENT TECHNIQUE) </li></ul>
  6. 6. Connecting to the Database – Cont.. <ul><li>Now, let's see what PDO has to offer. As PDO is fully object-oriented, we will be dealing with connection objects, and further interaction with the database will involve calling various methods of these objects. </li></ul><ul><li>With PDO, we will always have to explicitly use the connection object, since there is no other way of calling its methods. </li></ul><ul><li>Each of the three above connections could be established in the following manner: </li></ul><ul><ul><li>For MySQL: </li></ul></ul><ul><ul><ul><li>$conn = new PDO(&quot;mysql:host=$host;dbname=$db&quot;, $user, $pass); </li></ul></ul></ul><ul><ul><li>For SQLite: </li></ul></ul><ul><ul><ul><li>$conn = new PDO(&quot;sqlite:$db&quot;); </li></ul></ul></ul><ul><ul><li>For PostgreSQL : </li></ul></ul><ul><ul><ul><li>$conn = new PDO(&quot;pgsql:host=$host dbname=$db&quot;, $user, $pass); </li></ul></ul></ul>
  7. 7. Connecting to the Database – Cont.. <ul><li>As you can see, the only part that is changing here is the first argument passed to the PDO constructor. For SQLite, which does not utilize username and password, the second and third arguments can be skipped. </li></ul><ul><li>SQLite is not a database server, but it is an embedded SQL database library that operates on local files. More information about SQLite can be found at and more information about using SQLite with PHP can be found at </li></ul>
  8. 8. Connecting to the Database – Connection Strings <ul><li>As you have seen in previous example, PDO uses the so-called connection strings (or Data Source Names, abbreviated to DSN) that allow the PDO constructor to select proper driver and pass subsequent method calls to it. </li></ul><ul><li>These connection strings or DSNs are different for every database management system and are the only things that you will have to change. </li></ul><ul><li>Their advantage over using traditional methods of creating database connection is that you don't have to modify your code if you change the database management system. </li></ul><ul><li>A connection string can be defined in a configuration file and that file gets processed by your application. Should your database (data source) change, you just edit that configuration file and the rest of your code is kept intact. </li></ul>
  9. 9. Connecting to the Database – Connection Strings <ul><li>Create the connection object </li></ul><ul><ul><li>$conn = new PDO( $connStr , $user, $pass); </li></ul></ul><ul><li>DB connection string and username/password </li></ul><ul><ul><li>$connStr = 'mysql:host=localhost;dbname=pdo'; </li></ul></ul><ul><ul><li>$user = 'root'; </li></ul></ul><ul><ul><li>$pass = 'root'; </li></ul></ul><ul><li>The three connection strings looked like the following: </li></ul><ul><ul><li>mysql:host=localhost;dbname=cars </li></ul></ul><ul><ul><li>sqlite:/path/to/cars.db </li></ul></ul><ul><ul><li>pgsql:host=localhost dbname=cars </li></ul></ul><ul><li>As we can see, the prefix (the substring before the first semicolon) always keeps the name of the PDO driver. </li></ul><ul><li>Since we don't have to use different functions to create a connection with PDO, this prefix tells us which internal driver should be used. The rest of the string is parsed by that driver to further initiate the connection. </li></ul>
  10. 10. Issuing SQL Queries <ul><li>Previously, we would have had to call different functions, depending on the database: </li></ul><ul><li>Let's keep our SQL in a single variable </li></ul><ul><ul><li>$sql = 'SELECT DISTINCT make FROM cars ORDER BY make'; </li></ul></ul><ul><li>Now, assuming MySQL : </li></ul><ul><ul><li>mysql_connect('localhost', 'boss', 'password'); </li></ul></ul><ul><ul><li>mysql_select_db('cars'); </li></ul></ul><ul><ul><li>$q = mysql_query($sql); </li></ul></ul><ul><li>For SQLite we would do: </li></ul><ul><ul><li>$dbh = sqlite_open('/path/to/cars.ldb', 0666); </li></ul></ul><ul><ul><li>$q = sqlite_query($sql, $dbh); </li></ul></ul><ul><li>And for PostgreSQL : </li></ul><ul><ul><li>pg_connect(&quot;host=localhost dbname=cars user=boss </li></ul></ul><ul><ul><li>password=password&quot;); </li></ul></ul><ul><ul><li>$q = pg_query($sql); </li></ul></ul>
  11. 11. Issuing SQL Queries – Cont… <ul><li>Now that we are using PDO, we can do the following: </li></ul><ul><ul><li>Assume the $connStr variable holds a valid connection string </li></ul></ul><ul><ul><li>$sql = 'SELECT DISTINCT make FROM cars ORDER BY make'; </li></ul></ul><ul><ul><li>$conn = new PDO($connStr, 'boss', 'password'); </li></ul></ul><ul><ul><li>$q = $conn->query($sql); </li></ul></ul><ul><li>As you can see, doing things the PDO way is not too different from traditional methods of issuing queries. Also, here it should be underlined, that a call to $conn->query() is returning another object of class PDOStatement , unlike the calls to mysql_query(), sqlite_query(), and pg_query(), which return PHP variables of the resource type. </li></ul>
  12. 12. Issuing SQL Queries – Cont… <ul><li>The PDO class defines a single method for quoting strings so that they can be used safely in queries. </li></ul><ul><ul><li>$m = $conn->quote($make); </li></ul></ul><ul><ul><li>$q = $conn->query(&quot;SELECT sum(price) FROM cars WHERE make=$m&quot;); </li></ul></ul><ul><li>Now that we have issued our query, we will want to see its results. As the query in the last example will always return just one row, we will want more rows. Again, the three databases will require us to call different functions on the $q variable that was returned from one of the three calls to mysql_query(), sqlite_query(), or pg_query(). So our code for getting all the cars will look similar to this: </li></ul>
  13. 13. <ul><li>Assume the query is in the $sql variable </li></ul><ul><ul><li>$sql = &quot;SELECT DISTINCT make FROM cars ORDER BY make&quot;; </li></ul></ul><ul><li>For MySQL : </li></ul><ul><ul><li>$q = mysql_query($sql); </li></ul></ul><ul><ul><li>while($r = mysql_fetch_assoc($q)) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>echo $r['make'], &quot; &quot;; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>For SQLite : </li></ul><ul><ul><li>$q = sqlite_query($dbh, $sql); </li></ul></ul><ul><ul><li>while($r = sqlite_fetch_array($q, SQLITE_ASSOC)) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>echo $r['make'], &quot; &quot;; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>And, finally, PostgreSQL : </li></ul><ul><ul><li>$q = pg_query($sql); </li></ul></ul><ul><ul><li>while($r = pg_fetch_assoc($q)) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>echo $r['make'], &quot; &quot;; </li></ul></ul><ul><ul><li>} </li></ul></ul>
  14. 14. Issuing SQL Queries – Cont… <ul><li>As you may already have guessed, things are pretty straightforward when it comes to PDO: We don't care what the underlying database is, and the methods for fetching rows are the same across all databases. So, the above code could be rewritten for PDO in the following way: </li></ul><ul><li>mysql_fetch_array(), sqlite_fetch_array() without the second parameter, or pg_fetch_array().) </li></ul><ul><li>$q = $conn->query(&quot;SELECT DISTINCT make FROM cars ORDER BY </li></ul><ul><li>make&quot;); </li></ul><ul><ul><li>while($r = $q->fetch( PDO::FETCH_ASSOC )) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>echo $r['make'], &quot; &quot;; </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>Nothing is different from what happens before. One thing to note here is that we explicitly specified the PDO::FETCH_ASSOC fetch style constant here, since PDO's default behavior is to fetch the result rows as arrays indexed both by column name and number. (This behavior is similar to mysql_fetch_array(), sqlite_fetch_array() without the second parameter, or pg_fetch_array().) </li></ul>
  15. 15. <ul><li>Issue the query </li></ul><ul><ul><li>$q = $conn->query(&quot;SELECT AS authorId, firstName, </li></ul></ul><ul><ul><li>lastName, books.* FROM authors, books WHERE ORDER BY title&quot;); </li></ul></ul><ul><ul><li>$books = $q->fetchAll(PDO::FETCH_ASSOC) ; </li></ul></ul><ul><ul><li>foreach($books as $r) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>?> </li></ul></ul><ul><ul><ul><li><tr> </li></ul></ul></ul><ul><ul><ul><li><td><a href=&quot;author.php?id=<?=$r['authorId']?>&quot;> </li></ul></ul></ul><ul><ul><ul><li><?=htmlspecialchars(&quot;$r[firstName] $r[lastName]&quot;)?></a></td> </li></ul></ul></ul><ul><ul><ul><li><td><?=htmlspecialchars($r['title'])?></td> </li></ul></ul></ul><ul><ul><ul><li><td><?=htmlspecialchars($r['isbn'])?></td> </li></ul></ul></ul><ul><ul><ul><li><td><?=htmlspecialchars($r['publisher'])?></td> </li></ul></ul></ul><ul><ul><ul><li><td><?=htmlspecialchars($r['year'])?></td> </li></ul></ul></ul><ul><ul><ul><li><td><?=htmlspecialchars($r['summary'])?></td> </li></ul></ul></ul><ul><ul><ul><li></tr> </li></ul></ul></ul><ul><ul><li><?php } ?> </li></ul></ul>
  16. 16. Issuing SQL Queries – Cont… <ul><li>For example, MySQL extends the SQL syntax with this form of insert: </li></ul><ul><ul><li>INSERT INTO mytable SET x=1, y='two'; </li></ul></ul><ul><li>This kind of SQL code is not portable, as other databases do not understand this way of doing inserts. To ensure that your inserts work across databases, you should replace the above code with : </li></ul><ul><ul><li>INSERT INTO mytable(x, y) VALUES(1, 'two'); </li></ul></ul>
  17. 17. Error Handling <ul><li>Of course, the above examples didn't provide for any error checking, so they are not very useful for real-life applications. </li></ul><ul><li>When working with a database, we should check for errors when opening the connection to the database, when selecting the database and after issuing every query. </li></ul><ul><li>Most web applications, however, just need to display an error message when something goes wrong (without going into error detail, which could reveal some sensitive information). </li></ul><ul><li>However, when debugging an error, you (as the developer) would need the most detailed error information possible so that you can debug the error in the shortest possible time. </li></ul><ul><li>One simplistic scenario would be to abort the script and present the error message (although this is something you probably would not want to do). </li></ul>
  18. 18. Error Handling – Cont… <ul><li>Depending on the database, our code might look like this: </li></ul><ul><li>For Sqlite </li></ul><ul><ul><li>$dbh = sqlite_open('/path/to/cars.ldb', 0666) or die ('Error opening SQLite database: ' . sqlite_error_string(sqlite_last_error($dbh)) ); </li></ul></ul><ul><ul><li>$q = sqlite_query(&quot;SELECT DISTINCT make FROM cars ORDER BY make&quot;,$dbh) or </li></ul></ul><ul><ul><li>die('Could not execute query because: '. sqlite_error_string(sqlite_last_error($dbh)) ); </li></ul></ul><ul><li>For PostgreSQL </li></ul><ul><ul><li>pg_connect(&quot;host=localhost dbname=cars;user=boss;password=password&quot;) </li></ul></ul><ul><ul><li>or die('Could not connect to PostgreSQL: '. pg_last_error() ); </li></ul></ul><ul><ul><li>$q = pg_query(&quot;SELECT DISTINCT make FROM cars ORDER BY make&quot;) </li></ul></ul><ul><ul><li>or die('Could not execute query because: ' . pg_last_error() ); </li></ul></ul><ul><li>As you can see, error handling is starting to get a bit different for SQLite compared to MySQL and PostgreSQL. (Note the call to sqlite_error_string (sqlite_last_error($dbh)).) </li></ul>
  19. 19. Error Handling – Cont… <ul><li>PDO error handling </li></ul><ul><li>Assume the connection string is one of the following: </li></ul><ul><ul><li>// $connStr = 'mysql:host=localhost;dbname=cars' </li></ul></ul><ul><ul><li>// $connStr = 'sqlite:/path/to/cars.ldb'; </li></ul></ul><ul><ul><li>// $connStr = 'pgsql:host=localhost dbname=cars'; </li></ul></ul><ul><ul><li>try </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>$conn = new PDO($connStr, 'boss', 'password'); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>catch(PDOException $pe) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>die('Could not connect to the database because: ' . </li></ul></ul><ul><ul><li>$pe->getMessage(); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>$q = $conn->query(&quot;SELECT DISTINCT make FROM cars ORDER BY make&quot;); </li></ul></ul><ul><ul><li>if(!$q) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><li>$ei = $conn->errorInfo(); </li></ul></ul><ul><ul><li>die('Could not execute query because: ' . $ei[2]); </li></ul></ul><ul><ul><li>} </li></ul></ul>