Your SlideShare is downloading. ×
0
PHP 101: PDO                            or:How I Learned to Stop Worrying and Love        Data Access Abstraction         ...
What is PDO?• PDO == PHP Data Objects• Lightweight, consistent interface for  accessing databases in PHP• Provides data ac...
Drivers include . . .• MySQL• PostgreSQL• SQL Server• SQLite• and more . . .
Which drivers do I have?•   var_dump(PDO::getAvailableDrivers());•   If you don’t see what you need, check php.ini
Working with databases• Solved problem, you don’t have to write  anything yourself• PHP and MySQL have an especially rich ...
Let’s look at sometypical procedural code
What we’re building
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
mysql<?php$conn = mysql_connect(localhost, testuser, testpass)    or die(Could not connect:  . mysql_error());mysql_select...
Oops!Should have used mysqli!
mysqli<?php$conn = mysqli_connect(localhost, testuser, testpass, bookshelf)    or die(Could not connect:  . mysqli_connect...
Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants que...
Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants que...
Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants que...
Changing DB vendors?     Have fun with that.
sqlsrv<?php$connectionInfo = array(    Database => bookshelf,    UID => testuser,    PWD => testpass);$conn = sqlsrv_conne...
sqlsrv<?php$connectionInfo = array(    Database => bookshelf,    UID => testuser,    PWD => testpass);$conn = sqlsrv_conne...
sqlsrv<?php$connectionInfo = array(    Database => bookshelf,    UID => testuser,    PWD => testpass);$conn = sqlsrv_conne...
sqlsrv<?php$connectionInfo = array(    Database => bookshelf,    UID => testuser,    PWD => testpass);$conn = sqlsrv_conne...
sqlsrv<?php$connectionInfo = array(    Database => bookshelf,    UID => testuser,    PWD => testpass);$conn = sqlsrv_conne...
But what can you do     about it?
You could roll your own<?phpclass MyDb{    public function __construct($host, $username, $password, $dbname)    {    }    ...
Or don’t and use PDO
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
<?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array(    PDO::ATTR...
But I’m going to use SQLite in DEV . . .
No problem!Change the dsn, username, and password. Done.   $dsn = mysql:host=localhost;dbname=bookshelf;   $username = tes...
Connecting• DSN required, username & pass optional• A connection error always throws an    Exception, so use try/catch•   ...
Errors and Exceptions• Three error modes  •   PDO::ERRMODE_SILENT  •   PDO::ERRMODE_WARNING  •   PDO::ERRMODE_EXCEPTION• A...
Insert, Update, Delete• PDO::exec()• Returns # rows affected• Won’t return results of SELECT• Won’t escape data (use PDO::...
Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM book...
Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM book...
Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM book...
Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM book...
In almost all cases, favor  prepared statements    over PDO::exec()
Prepared statements• To know them is to love them• No more SQL injection• Can execute same statement multiple times  with ...
Prepared statements                    Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title...
Prepared statements                    Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title...
Prepared statements                    Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title...
Prepared statements                    Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title...
Prepared statements                  Using positional parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (?, ...
Prepared statements          Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:t...
Prepared statements          Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:t...
Prepared statements          Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:t...
Select• Gets data from the database• Results returned as PDOStatement• How data is fetched from statement  depends on fetc...
Fetch modes• Can be set in constructor or later with  PDO::setAttribute() or  PDOStatement::setFetchMode()• PDO::FETCH_ASS...
Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all...
Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all...
Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all...
Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all...
Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all...
Fetching       PDOStatement implements Traversable,              which allows you to:$stmt = $dbh->query(SELECT * FROM boo...
Fetching       PDOStatement implements Traversable,              which allows you to:$stmt = $dbh->query(SELECT * FROM boo...
Fetching                   PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY t...
Fetching                   PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY t...
Fetching                   PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY t...
But wait, there’s more!
PDO::lastInsertId()• Returns the ID of the last inserted row• Or the last value from a sequence object• Be careful, some d...
Transactions• PDO::beginTransaction()• PDO::commit()• PDO::rollback()• Check your DB documentation for support
Benefits• Maintainability• Portability (with a few vendor specific  caveats)• Safety (prepared statements)• Object oriented
Drawbacks• Not all vendor specific features supported• Interface is almost the same for all  databases• Slower in some case...
Portable, mostly• Every DB has its own oddities and gotchas• PDO offers data access abstraction• You’ll likely still have ...
Credits•   PHP Data Objects by Wez Furlong: http://    www.slideshare.net/wezfurlong/php-data-objects•   Nettuts+: http://...
Questions?
Thanks!• @JeremyKendall• jeremy@jeremykendall.net• http://about.me/jeremykendall
Php 101: PDO
Upcoming SlideShare
Loading in...5
×

Php 101: PDO

1,180

Published on

Published in: Technology
1 Comment
10 Likes
Statistics
Notes
No Downloads
Views
Total Views
1,180
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
145
Comments
1
Likes
10
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript of "Php 101: PDO"

    1. 1. PHP 101: PDO or:How I Learned to Stop Worrying and Love Data Access Abstraction Jeremy Kendall | Memphis PHP | July 26, 2012
    2. 2. What is PDO?• PDO == PHP Data Objects• Lightweight, consistent interface for accessing databases in PHP• Provides data access abstraction, not database abstraction• Ships with PHP 5.1• PECL extension for 5.0
    3. 3. Drivers include . . .• MySQL• PostgreSQL• SQL Server• SQLite• and more . . .
    4. 4. Which drivers do I have?• var_dump(PDO::getAvailableDrivers());• If you don’t see what you need, check php.ini
    5. 5. Working with databases• Solved problem, you don’t have to write anything yourself• PHP and MySQL have an especially rich history• CRUD is the easy part• Creating clean, maintainable code is the challenge
    6. 6. Let’s look at sometypical procedural code
    7. 7. What we’re building
    8. 8. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    9. 9. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    10. 10. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    11. 11. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    12. 12. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    13. 13. mysql<?php$conn = mysql_connect(localhost, testuser, testpass) or die(Could not connect: . mysql_error());mysql_select_db(bookshelf) or die(Could not select bookshelf);$result = mysql_query(SELECT * FROM bookshelf ORDER BY title, $conn) or die(Invalid query: . mysql_error());?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysql_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysql_close($conn);
    14. 14. Oops!Should have used mysqli!
    15. 15. mysqli<?php$conn = mysqli_connect(localhost, testuser, testpass, bookshelf) or die(Could not connect: . mysqli_connect_error());$result = mysqli_query($conn, SELECT * FROM bookshelf ORDER BY title) or die(Invalid query: . mysqli_error($conn));?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = mysqli_fetch_assoc($result)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpmysqli_close($conn);
    16. 16. Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants query first and connection second$result = mysql_query($query, $conn);// mysqli_query is exactly opposite$result = mysqli_query($conn, $query);
    17. 17. Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants query first and connection second$result = mysql_query($query, $conn);// mysqli_query is exactly opposite$result = mysqli_query($conn, $query);
    18. 18. Refactoring problems// You cant simply find and replace// because of differences in the interfaces// mysql_query wants query first and connection second$result = mysql_query($query, $conn);// mysqli_query is exactly opposite$result = mysqli_query($conn, $query);
    19. 19. Changing DB vendors? Have fun with that.
    20. 20. sqlsrv<?php$connectionInfo = array( Database => bookshelf, UID => testuser, PWD => testpass);$conn = sqlsrv_connect(serverNameinstanceName, $connectionInfo);$stmt = sqlsrv_query($conn, SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpsqlsrv_close($conn);
    21. 21. sqlsrv<?php$connectionInfo = array( Database => bookshelf, UID => testuser, PWD => testpass);$conn = sqlsrv_connect(serverNameinstanceName, $connectionInfo);$stmt = sqlsrv_query($conn, SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpsqlsrv_close($conn);
    22. 22. sqlsrv<?php$connectionInfo = array( Database => bookshelf, UID => testuser, PWD => testpass);$conn = sqlsrv_connect(serverNameinstanceName, $connectionInfo);$stmt = sqlsrv_query($conn, SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpsqlsrv_close($conn);
    23. 23. sqlsrv<?php$connectionInfo = array( Database => bookshelf, UID => testuser, PWD => testpass);$conn = sqlsrv_connect(serverNameinstanceName, $connectionInfo);$stmt = sqlsrv_query($conn, SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpsqlsrv_close($conn);
    24. 24. sqlsrv<?php$connectionInfo = array( Database => bookshelf, UID => testuser, PWD => testpass);$conn = sqlsrv_connect(serverNameinstanceName, $connectionInfo);$stmt = sqlsrv_query($conn, SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table><?phpsqlsrv_close($conn);
    25. 25. But what can you do about it?
    26. 26. You could roll your own<?phpclass MyDb{ public function __construct($host, $username, $password, $dbname) { } public function query($sql, array $bind) { } // . . .}
    27. 27. Or don’t and use PDO
    28. 28. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    29. 29. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    30. 30. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    31. 31. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    32. 32. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    33. 33. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    34. 34. <?php$dsn = mysql:host=localhost;dbname=bookshelf;$username = testuser;$password = testpass;$options = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC);try { $dbh = new PDO($dsn, $username, $password, $options);} catch (PDOException $e) { echo Error!: . $e->getMessage(); die();}// $result is an array, so we can use array functions rather than db vendor functions$result = $dbh->query(SELECT * FROM bookshelf ORDER BY title)->fetchAll();?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($result as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    35. 35. But I’m going to use SQLite in DEV . . .
    36. 36. No problem!Change the dsn, username, and password. Done. $dsn = mysql:host=localhost;dbname=bookshelf; $username = testuser; $password = testpass; becomes $dsn = sqlite: . realpath(./data/db/bookshelf.db); $username = null; $password = null;
    37. 37. Connecting• DSN required, username & pass optional• A connection error always throws an Exception, so use try/catch• Closing a connection is as simple as $dbh = null
    38. 38. Errors and Exceptions• Three error modes • PDO::ERRMODE_SILENT • PDO::ERRMODE_WARNING • PDO::ERRMODE_EXCEPTION• Always use exceptions• No, really, use exceptions
    39. 39. Insert, Update, Delete• PDO::exec()• Returns # rows affected• Won’t return results of SELECT• Won’t escape data (use PDO::quote())
    40. 40. Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM bookshelf WHERE title = $title");/* Return number of rows that were deleted */print("Deleted $count rows.n");
    41. 41. Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM bookshelf WHERE title = $title");/* Return number of rows that were deleted */print("Deleted $count rows.n");
    42. 42. Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM bookshelf WHERE title = $title");/* Return number of rows that were deleted */print("Deleted $count rows.n");
    43. 43. Delete example/* quote string */$title = $dbh->quote(Refactoring);/* Delete a book */$count = $dbh->exec("DELETE FROM bookshelf WHERE title = $title");/* Return number of rows that were deleted */print("Deleted $count rows.n");
    44. 44. In almost all cases, favor prepared statements over PDO::exec()
    45. 45. Prepared statements• To know them is to love them• No more SQL injection• Can execute same statement multiple times with different values• Efficient (in most cases)• Positional, named• The one feature PDO emulates
    46. 46. Prepared statements Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->bindParam(title, $title);$statement->bindParam(author, $author);$books = array( "Clean Code" => "Robert C. Martin", "Refactoring" => "Martin Fowler", "Test-Driven Development" => "Kent Beck", "The Agile Samurai" => "Jonathan Rasmusson", "Working Effectively with Legacy Code" => "Michael Feathers");foreach ($books as $title => $author) { $setup->execute();}
    47. 47. Prepared statements Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->bindParam(title, $title);$statement->bindParam(author, $author);$books = array( "Clean Code" => "Robert C. Martin", "Refactoring" => "Martin Fowler", "Test-Driven Development" => "Kent Beck", "The Agile Samurai" => "Jonathan Rasmusson", "Working Effectively with Legacy Code" => "Michael Feathers");foreach ($books as $title => $author) { $setup->execute();}
    48. 48. Prepared statements Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->bindParam(title, $title);$statement->bindParam(author, $author);$books = array( "Clean Code" => "Robert C. Martin", "Refactoring" => "Martin Fowler", "Test-Driven Development" => "Kent Beck", "The Agile Samurai" => "Jonathan Rasmusson", "Working Effectively with Legacy Code" => "Michael Feathers");foreach ($books as $title => $author) { $setup->execute();}
    49. 49. Prepared statements Using named parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->bindParam(title, $title);$statement->bindParam(author, $author);$books = array( "Clean Code" => "Robert C. Martin", "Refactoring" => "Martin Fowler", "Test-Driven Development" => "Kent Beck", "The Agile Samurai" => "Jonathan Rasmusson", "Working Effectively with Legacy Code" => "Michael Feathers");foreach ($books as $title => $author) { $setup->execute();}
    50. 50. Prepared statements Using positional parameters:$sql = "INSERT INTO bookshelf (title, author) VALUES (?, ?)";$statement = $dbh->prepare($sql);$statement->bindParam(1, $title);$statement->bindParam(2, $author);$books = array( "Clean Code" => "Robert C. Martin", "Refactoring" => "Martin Fowler", "Test-Driven Development" => "Kent Beck", "The Agile Samurai" => "Jonathan Rasmusson", "Working Effectively with Legacy Code" => "Michael Feathers");foreach ($books as $title => $author) { $setup->execute();}
    51. 51. Prepared statements Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->execute(array(title => $title, author => $author));
    52. 52. Prepared statements Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->execute(array(title => $title, author => $author));
    53. 53. Prepared statements Array of named params to PDO::execute$sql = "INSERT INTO bookshelf (title, author) VALUES (:title, :author)";$statement = $dbh->prepare($sql);$statement->execute(array(title => $title, author => $author));
    54. 54. Select• Gets data from the database• Results returned as PDOStatement• How data is fetched from statement depends on fetch mode• Grab all results at once with fetchAll()
    55. 55. Fetch modes• Can be set in constructor or later with PDO::setAttribute() or PDOStatement::setFetchMode()• PDO::FETCH_ASSOC• PDO::FETCH_BOTH (default)• PDO::FETCH_NUM• PDO::FETCH_OBJ• to name a few . . .
    56. 56. Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all results$books = $stmt->fetchAll();// Returns next row in manner determined by fetch mode$row = $stmt->fetch();// Can choose fetch mode at time of fetch$row = $stmt->fetch(PDO::FETCH_OBJ);
    57. 57. Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all results$books = $stmt->fetchAll();// Returns next row in manner determined by fetch mode$row = $stmt->fetch();// Can choose fetch mode at time of fetch$row = $stmt->fetch(PDO::FETCH_OBJ);
    58. 58. Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all results$books = $stmt->fetchAll();// Returns next row in manner determined by fetch mode$row = $stmt->fetch();// Can choose fetch mode at time of fetch$row = $stmt->fetch(PDO::FETCH_OBJ);
    59. 59. Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all results$books = $stmt->fetchAll();// Returns next row in manner determined by fetch mode$row = $stmt->fetch();// Can choose fetch mode at time of fetch$row = $stmt->fetch(PDO::FETCH_OBJ);
    60. 60. Fetching// Gets all books in database$stmt = $dbh->query("SELECT * FROM bookshelf ORDER BY title");// Returns array of all results$books = $stmt->fetchAll();// Returns next row in manner determined by fetch mode$row = $stmt->fetch();// Can choose fetch mode at time of fetch$row = $stmt->fetch(PDO::FETCH_OBJ);
    61. 61. Fetching PDOStatement implements Traversable, which allows you to:$stmt = $dbh->query(SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($stmt as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    62. 62. Fetching PDOStatement implements Traversable, which allows you to:$stmt = $dbh->query(SELECT * FROM bookshelf ORDER BY title);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php foreach ($stmt as $row) { echo "<tr>"; echo "<td>{$row[title]}</td><td>{$row[author]}</td>"; echo "</tr>"; } ?></table>
    63. 63. Fetching PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY title);$stmt->bindColumn(title, $title);$stmt->bindColumn(author, $author);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($stmt->fetch(PDO::FETCH_BOUND)) { echo "<tr>"; echo "<td>$title</td><td>$author</td>"; echo "</tr>"; } ?></table>
    64. 64. Fetching PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY title);$stmt->bindColumn(title, $title);$stmt->bindColumn(author, $author);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($stmt->fetch(PDO::FETCH_BOUND)) { echo "<tr>"; echo "<td>$title</td><td>$author</td>"; echo "</tr>"; } ?></table>
    65. 65. Fetching PDO::FETCH_BOUND is slick$stmt = $dbh->query(SELECT id, title, author FROM bookshelf ORDER BY title);$stmt->bindColumn(title, $title);$stmt->bindColumn(author, $author);?><table> <tr> <th>Title</th><th>Author</th> </tr> <?php while ($stmt->fetch(PDO::FETCH_BOUND)) { echo "<tr>"; echo "<td>$title</td><td>$author</td>"; echo "</tr>"; } ?></table>
    66. 66. But wait, there’s more!
    67. 67. PDO::lastInsertId()• Returns the ID of the last inserted row• Or the last value from a sequence object• Be careful, some databases don’t support this and may exhibit unexpected behavior
    68. 68. Transactions• PDO::beginTransaction()• PDO::commit()• PDO::rollback()• Check your DB documentation for support
    69. 69. Benefits• Maintainability• Portability (with a few vendor specific caveats)• Safety (prepared statements)• Object oriented
    70. 70. Drawbacks• Not all vendor specific features supported• Interface is almost the same for all databases• Slower in some cases• Mediocre Oracle support (who uses Oracle?)
    71. 71. Portable, mostly• Every DB has its own oddities and gotchas• PDO offers data access abstraction• You’ll likely still have to tweak if you’re doing anything other than very simple CRUD• Still better than mysql_*, mysqli_*, sqlsrv_*• Choose a DBAL like Doctrine if you need more
    72. 72. Credits• PHP Data Objects by Wez Furlong: http:// www.slideshare.net/wezfurlong/php-data-objects• Nettuts+: http://net.tutsplus.com/tutorials/php/why-you- should-be-using-phps-pdo-for-database-access/• Introduction to PDO: http://www.dreamincode.net/ forums/topic/214733-introduction-to-pdo/• php.net: http://us.php.net/manual/en/class.pdo.php
    73. 73. Questions?
    74. 74. Thanks!• @JeremyKendall• jeremy@jeremykendall.net• http://about.me/jeremykendall
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×