SlideShare a Scribd company logo
1 of 75
PHP 101: PDO
                            or:
How I Learned to Stop Worrying and Love
        Data Access Abstraction




         Jeremy Kendall | Memphis PHP | July 26, 2012
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
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
  history
• CRUD is the easy part
• Creating clean, maintainable code is the
  challenge
Let’s look at some
typical procedural code
What we’re building
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>
<?php
mysql_close($conn);
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>
<?php
mysql_close($conn);
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>
<?php
mysql_close($conn);
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>
<?php
mysql_close($conn);
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>
<?php
mysql_close($conn);
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>
<?php
mysql_close($conn);
Oops!
Should have used mysqli!
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>
<?php
mysqli_close($conn);
Refactoring problems
// You can't 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);
Refactoring problems
// You can't 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);
Refactoring problems
// You can't 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);
Changing DB vendors?
     Have fun with that.
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>
<?php
sqlsrv_close($conn);
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>
<?php
sqlsrv_close($conn);
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>
<?php
sqlsrv_close($conn);
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>
<?php
sqlsrv_close($conn);
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>
<?php
sqlsrv_close($conn);
But what can you do
     about it?
You could roll your own
<?php

class MyDb
{
    public function __construct($host, $username, $password, $dbname)
    {

    }

    public function query($sql, array $bind)
    {

    }

    // . . .
}
Or don’t and use PDO
<?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>
<?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>
<?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>
<?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>
<?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>
<?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>
<?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>
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 = 'testuser';
   $password = 'testpass';


                   becomes
   $dsn = 'sqlite:' . realpath('./data/db/bookshelf.db');
   $username = null;
   $password = null;
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
Errors and Exceptions
• Three error modes
  •   PDO::ERRMODE_SILENT

  •   PDO::ERRMODE_WARNING

  •   PDO::ERRMODE_EXCEPTION


• Always use exceptions
• No, really, use exceptions
Insert, Update, Delete
• PDO::exec()
• Returns # rows affected
• Won’t return results of SELECT
• Won’t escape data (use PDO::quote())
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");
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");
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");
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");
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 different values
• Efficient (in most cases)
• Positional, named
• The one feature PDO emulates
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();
}
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();
}
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();
}
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();
}
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();
}
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));
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));
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));
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()
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 . . .
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);
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);
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);
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);
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);
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>
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>
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>
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>
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>
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 databases don’t support
  this and may exhibit unexpected behavior
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 cases
• Mediocre Oracle support (who uses
  Oracle?)
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
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
Questions?
Thanks!

• @JeremyKendall
• jeremy@jeremykendall.net
• http://about.me/jeremykendall

More Related Content

What's hot

MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MYXPLAIN
 
Hibernate
Hibernate Hibernate
Hibernate Sunil OS
 
PGConf.ASIA 2017 Logical Replication Internals (English)
PGConf.ASIA 2017 Logical Replication Internals (English)PGConf.ASIA 2017 Logical Replication Internals (English)
PGConf.ASIA 2017 Logical Replication Internals (English)Noriyoshi Shinoda
 
Базы данных в 2020
Базы данных в 2020Базы данных в 2020
Базы данных в 2020Timur Shemsedinov
 
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기PgDay.Seoul
 
關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧Orange Tsai
 
Database Anti Patterns
Database Anti PatternsDatabase Anti Patterns
Database Anti PatternsRobert Treat
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Traceoysteing
 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORMOdoo
 
XXE: How to become a Jedi
XXE: How to become a JediXXE: How to become a Jedi
XXE: How to become a JediYaroslav Babin
 
Bash Script Disk Space Utilization Report and EMail
Bash Script Disk Space Utilization Report and EMailBash Script Disk Space Utilization Report and EMail
Bash Script Disk Space Utilization Report and EMailVCP Muthukrishna
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop NotesPamela Fox
 
Table partitioning in PostgreSQL + Rails
Table partitioning in PostgreSQL + RailsTable partitioning in PostgreSQL + Rails
Table partitioning in PostgreSQL + RailsAgnieszka Figiel
 
ListView RecyclerView.pptx
ListView RecyclerView.pptxListView RecyclerView.pptx
ListView RecyclerView.pptxOmakoiMalang
 

What's hot (20)

MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6MySQL Indexing - Best practices for MySQL 5.6
MySQL Indexing - Best practices for MySQL 5.6
 
JQuery UI
JQuery UIJQuery UI
JQuery UI
 
Hibernate
Hibernate Hibernate
Hibernate
 
JDBC
JDBCJDBC
JDBC
 
Module 3 - Intro to Bootstrap
Module 3 - Intro to BootstrapModule 3 - Intro to Bootstrap
Module 3 - Intro to Bootstrap
 
PGConf.ASIA 2017 Logical Replication Internals (English)
PGConf.ASIA 2017 Logical Replication Internals (English)PGConf.ASIA 2017 Logical Replication Internals (English)
PGConf.ASIA 2017 Logical Replication Internals (English)
 
Podstawy php
Podstawy phpPodstawy php
Podstawy php
 
Базы данных в 2020
Базы данных в 2020Базы данных в 2020
Базы данных в 2020
 
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
[Pgday.Seoul 2017] 8. PostgreSQL 10 새기능 소개 - 김상기
 
關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧
 
Database Anti Patterns
Database Anti PatternsDatabase Anti Patterns
Database Anti Patterns
 
The MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer TraceThe MySQL Query Optimizer Explained Through Optimizer Trace
The MySQL Query Optimizer Explained Through Optimizer Trace
 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORM
 
XXE: How to become a Jedi
XXE: How to become a JediXXE: How to become a Jedi
XXE: How to become a Jedi
 
PostgreSQL - Lección 10 - Vistas
PostgreSQL - Lección 10 - VistasPostgreSQL - Lección 10 - Vistas
PostgreSQL - Lección 10 - Vistas
 
Bash Script Disk Space Utilization Report and EMail
Bash Script Disk Space Utilization Report and EMailBash Script Disk Space Utilization Report and EMail
Bash Script Disk Space Utilization Report and EMail
 
PHP Workshop Notes
PHP Workshop NotesPHP Workshop Notes
PHP Workshop Notes
 
Php with MYSQL Database
Php with MYSQL DatabasePhp with MYSQL Database
Php with MYSQL Database
 
Table partitioning in PostgreSQL + Rails
Table partitioning in PostgreSQL + RailsTable partitioning in PostgreSQL + Rails
Table partitioning in PostgreSQL + Rails
 
ListView RecyclerView.pptx
ListView RecyclerView.pptxListView RecyclerView.pptx
ListView RecyclerView.pptx
 

Viewers also liked

PHP - PDO Objects
PHP - PDO ObjectsPHP - PDO Objects
PHP - PDO ObjectsAJINKYA N
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data ObjectsWez Furlong
 
PHP 7 performances from PHP 5
PHP 7 performances from PHP 5PHP 7 performances from PHP 5
PHP 7 performances from PHP 5julien pauli
 
PHP, Under The Hood - DPC
PHP, Under The Hood - DPCPHP, Under The Hood - DPC
PHP, Under The Hood - DPCAnthony Ferrara
 
Php internal architecture
Php internal architecturePhp internal architecture
Php internal architectureElizabeth Smith
 
Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)David de Boer
 
Internet of Things With PHP
Internet of Things With PHPInternet of Things With PHP
Internet of Things With PHPAdam Englander
 
PHP Optimization
PHP OptimizationPHP Optimization
PHP Optimizationdjesch
 
Laravel Beginners Tutorial 1
Laravel Beginners Tutorial 1Laravel Beginners Tutorial 1
Laravel Beginners Tutorial 1Vikas Chauhan
 
How PHP Works ?
How PHP Works ?How PHP Works ?
How PHP Works ?Ravi Raj
 
[Community Open Camp] 給 PHP 開發者的 VS Code 指南
[Community Open Camp] 給 PHP 開發者的 VS Code 指南[Community Open Camp] 給 PHP 開發者的 VS Code 指南
[Community Open Camp] 給 PHP 開發者的 VS Code 指南Shengyou Fan
 
LaravelConf Taiwan 2017 開幕
LaravelConf Taiwan 2017 開幕LaravelConf Taiwan 2017 開幕
LaravelConf Taiwan 2017 開幕Shengyou Fan
 
Route 路由控制
Route 路由控制Route 路由控制
Route 路由控制Shengyou Fan
 

Viewers also liked (16)

PHP - PDO Objects
PHP - PDO ObjectsPHP - PDO Objects
PHP - PDO Objects
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
 
PHP WTF
PHP WTFPHP WTF
PHP WTF
 
PHP 7 performances from PHP 5
PHP 7 performances from PHP 5PHP 7 performances from PHP 5
PHP 7 performances from PHP 5
 
PHP, Under The Hood - DPC
PHP, Under The Hood - DPCPHP, Under The Hood - DPC
PHP, Under The Hood - DPC
 
PHP 7 new engine
PHP 7 new enginePHP 7 new engine
PHP 7 new engine
 
Php
PhpPhp
Php
 
Php internal architecture
Php internal architecturePhp internal architecture
Php internal architecture
 
Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)
 
Internet of Things With PHP
Internet of Things With PHPInternet of Things With PHP
Internet of Things With PHP
 
PHP Optimization
PHP OptimizationPHP Optimization
PHP Optimization
 
Laravel Beginners Tutorial 1
Laravel Beginners Tutorial 1Laravel Beginners Tutorial 1
Laravel Beginners Tutorial 1
 
How PHP Works ?
How PHP Works ?How PHP Works ?
How PHP Works ?
 
[Community Open Camp] 給 PHP 開發者的 VS Code 指南
[Community Open Camp] 給 PHP 開發者的 VS Code 指南[Community Open Camp] 給 PHP 開發者的 VS Code 指南
[Community Open Camp] 給 PHP 開發者的 VS Code 指南
 
LaravelConf Taiwan 2017 開幕
LaravelConf Taiwan 2017 開幕LaravelConf Taiwan 2017 開幕
LaravelConf Taiwan 2017 開幕
 
Route 路由控制
Route 路由控制Route 路由控制
Route 路由控制
 

Similar to Php 101: PDO

The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Ex[1].3 php db connectivity
Ex[1].3 php db connectivityEx[1].3 php db connectivity
Ex[1].3 php db connectivityMouli Chandira
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodJeremy Kendall
 
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering CollegeDatabase Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering CollegeDhivyaa C.R
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
FYBSC IT Web Programming Unit V  Advanced PHP and MySQLFYBSC IT Web Programming Unit V  Advanced PHP and MySQL
FYBSC IT Web Programming Unit V Advanced PHP and MySQLArti Parab Academics
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegamehozayfa999
 
Php update and delet operation
Php update and delet operationPhp update and delet operation
Php update and delet operationsyeda zoya mehdi
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Latihan form login
Latihan form loginLatihan form login
Latihan form loginEdy Sinaga
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Masahiro Nagano
 

Similar to Php 101: PDO (20)

The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Ex[1].3 php db connectivity
Ex[1].3 php db connectivityEx[1].3 php db connectivity
Ex[1].3 php db connectivity
 
Php 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the GoodPhp 102: Out with the Bad, In with the Good
Php 102: Out with the Bad, In with the Good
 
UNIT V (5).pptx
UNIT V (5).pptxUNIT V (5).pptx
UNIT V (5).pptx
 
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering CollegeDatabase Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
Database Connectivity MYSQL by Dr.C.R.Dhivyaa Kongu Engineering College
 
Php (1)
Php (1)Php (1)
Php (1)
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Mysql & Php
Mysql & PhpMysql & Php
Mysql & Php
 
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
FYBSC IT Web Programming Unit V  Advanced PHP and MySQLFYBSC IT Web Programming Unit V  Advanced PHP and MySQL
FYBSC IT Web Programming Unit V Advanced PHP and MySQL
 
Php
PhpPhp
Php
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegame
 
php plus mysql
php plus mysqlphp plus mysql
php plus mysql
 
Php update and delet operation
Php update and delet operationPhp update and delet operation
Php update and delet operation
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
Php functions
Php functionsPhp functions
Php functions
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Shell.php
Shell.phpShell.php
Shell.php
 
Php My Sql
Php My SqlPhp My Sql
Php My Sql
 
Latihan form login
Latihan form loginLatihan form login
Latihan form login
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
 

More from Jeremy Kendall

Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPJeremy Kendall
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPJeremy Kendall
 
5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) CodeJeremy Kendall
 
Game Changing Dependency Management
Game Changing Dependency ManagementGame Changing Dependency Management
Game Changing Dependency ManagementJeremy Kendall
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkJeremy Kendall
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
PHP 102: Out with the Bad, In with the Good
PHP 102: Out with the Bad, In with the GoodPHP 102: Out with the Bad, In with the Good
PHP 102: Out with the Bad, In with the GoodJeremy Kendall
 
Intro to #memtech PHP 2011-12-05
Intro to #memtech PHP   2011-12-05Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP 2011-12-05Jeremy Kendall
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25Jeremy Kendall
 
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormZend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormJeremy Kendall
 
Zero to ZF in 10 Minutes
Zero to ZF in 10 MinutesZero to ZF in 10 Minutes
Zero to ZF in 10 MinutesJeremy Kendall
 
Tdd in php a brief example
Tdd in php   a brief exampleTdd in php   a brief example
Tdd in php a brief exampleJeremy Kendall
 
A Brief Introduction to Zend_Form
A Brief Introduction to Zend_FormA Brief Introduction to Zend_Form
A Brief Introduction to Zend_FormJeremy Kendall
 
Zero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesZero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesJeremy Kendall
 

More from Jeremy Kendall (15)

Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHPLeveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
 
5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code5 Ways to Awesome-ize Your (PHP) Code
5 Ways to Awesome-ize Your (PHP) Code
 
Game Changing Dependency Management
Game Changing Dependency ManagementGame Changing Dependency Management
Game Changing Dependency Management
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
PHP 102: Out with the Bad, In with the Good
PHP 102: Out with the Bad, In with the GoodPHP 102: Out with the Bad, In with the Good
PHP 102: Out with the Bad, In with the Good
 
Intro to #memtech PHP 2011-12-05
Intro to #memtech PHP   2011-12-05Intro to #memtech PHP   2011-12-05
Intro to #memtech PHP 2011-12-05
 
TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25TDD in PHP - Memphis PHP 2011-08-25
TDD in PHP - Memphis PHP 2011-08-25
 
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_FormZend_Form to the Rescue - A Brief Introduction to Zend_Form
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
 
Zero to ZF in 10 Minutes
Zero to ZF in 10 MinutesZero to ZF in 10 Minutes
Zero to ZF in 10 Minutes
 
Tdd in php a brief example
Tdd in php   a brief exampleTdd in php   a brief example
Tdd in php a brief example
 
A Brief Introduction to Zend_Form
A Brief Introduction to Zend_FormA Brief Introduction to Zend_Form
A Brief Introduction to Zend_Form
 
Zero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutesZero to Zend Framework in 10 minutes
Zero to Zend Framework in 10 minutes
 

Recently uploaded

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetEnjoy Anytime
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 

Recently uploaded (20)

The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 

Php 101: PDO

  • 1. PHP 101: PDO or: How I Learned to Stop Worrying and Love Data Access Abstraction Jeremy Kendall | Memphis PHP | July 26, 2012
  • 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. Drivers include . . . • MySQL • PostgreSQL • SQL Server • SQLite • and more . . .
  • 4. Which drivers do I have? • var_dump(PDO::getAvailableDrivers()); • If you don’t see what you need, check php.ini
  • 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. Let’s look at some typical procedural code
  • 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> <?php mysql_close($conn);
  • 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> <?php mysql_close($conn);
  • 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> <?php mysql_close($conn);
  • 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> <?php mysql_close($conn);
  • 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> <?php mysql_close($conn);
  • 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> <?php mysql_close($conn);
  • 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> <?php mysqli_close($conn);
  • 16. Refactoring problems // You can't 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. Refactoring problems // You can't 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. Refactoring problems // You can't 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. Changing DB vendors? Have fun with that.
  • 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> <?php sqlsrv_close($conn);
  • 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> <?php sqlsrv_close($conn);
  • 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> <?php sqlsrv_close($conn);
  • 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> <?php sqlsrv_close($conn);
  • 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> <?php sqlsrv_close($conn);
  • 25.
  • 26. But what can you do about it?
  • 27. You could roll your own <?php class MyDb { public function __construct($host, $username, $password, $dbname) { } public function query($sql, array $bind) { } // . . . }
  • 28. Or don’t and use PDO
  • 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. <?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. <?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. <?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. <?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. <?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. <?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>
  • 36. But I’m going to use SQLite in DEV . . .
  • 37. 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;
  • 38. 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
  • 39. Errors and Exceptions • Three error modes • PDO::ERRMODE_SILENT • PDO::ERRMODE_WARNING • PDO::ERRMODE_EXCEPTION • Always use exceptions • No, really, use exceptions
  • 40. Insert, Update, Delete • PDO::exec() • Returns # rows affected • Won’t return results of SELECT • Won’t escape data (use PDO::quote())
  • 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. 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. 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. 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");
  • 45. In almost all cases, favor prepared statements over PDO::exec()
  • 46. 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
  • 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. 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. 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. 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(); }
  • 51. 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(); }
  • 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. 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. 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));
  • 55. 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()
  • 56. 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 . . .
  • 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. 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. 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. 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. 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);
  • 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. 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>
  • 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. 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. 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>
  • 68. 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
  • 69. Transactions • PDO::beginTransaction() • PDO::commit() • PDO::rollback() • Check your DB documentation for support
  • 70. Benefits • Maintainability • Portability (with a few vendor specific caveats) • Safety (prepared statements) • Object oriented
  • 71. 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?)
  • 72. 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
  • 73. 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

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n