PDO


The PHP Data Objects (PDO) extension
defines a lightweight, consistent interface
for accessing databases in PHP.

http://bit.ly/IuhK25
http://slid.es/chrise86/pdo?token=GxBQWs8KV86MwE9rViLxqwCBDLAr

MySQL

  • MySQL is a database system used on the web
  • MySQL is a database system that runs on a server
  • MySQL is ideal for both small and large applications
  • MySQL is very fast, reliable, and easy to use
  • MySQL supports standard SQL
  • MySQL compiles on a number of platforms
  • MySQL is free to download and use
  • MySQL is developed, distributed, and supported by Oracle Corporation
  • MySQL is named after co-founder Monty Widenius's daughter: My

MySQL

  • Databases are useful when storing information categorically. A company may have a database with the following tables:
    • Employees
    • Products
    • Customers
    • Orders

Prerequisites


  • Open /Applications/MAMP/bin/php/php5.5.3/conf/php.ini
  • Find "error_reporting"
    • Make sure it = E_ALL
  • Find "display_errors"
    • Make sure it = On
  • Find "display_startup_errors"
    • Make sure it = On
  • Set opcache.revalidate_freq=0
    • If that doesn't stop caching, comment out all opcache related lines i.e. put a # in front of the line

Connecting to MySQL


<?php
  
  $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);

?>

General / Common terms

  • $dbh = "Database handle"
  • $sth = "Statement handle"
  • $stmt = "Statement"

Setting up connection


<?php
  $host  = "localhost";
  $user = "chris";
  $pass = "p4ssw0rd";
  $dbname = "dc2s10";

  try {
    $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    echo 'Connected to database';
  } catch(PDOException $e) {
    echo "<p>Oop, something went wrong.</p>";
    die("DB Error: ". $e->getMessage()); 
  }?>

Capturing errors


<?php
  $host  = "localhost";
  $user = "chris";
  $pass = "p4ssw0rd";
  $dbname = "dc2s10";

  try {
    $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    echo 'Connected to database';
  } catch(PDOException $e) {
    echo "<p>Oop, something went wrong.</p>";
    file_put_contents('PDOErrors.txt', $e->getMessage()."\n", FILE_APPEND);
    die("DB Error: ". $e->getMessage()); 
  }
?>

Trigger an Error


<?php
  $host  = "localhost";
  $user = "chris";
  $pass = "p4ssw0rd";
  $dbname = "dc2s10";

  try {
// deliberately trigger an error using "msql" instead of "mysql" $dbh = new PDO("msql:host=$host;dbname=$dbname", $user, $pass); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); echo 'Connected to database'; } catch(PDOException $e) { echo "<p>Oop, something went wrong.</p>"; file_put_contents('PDOErrors.txt', $e->getMessage()."\n", FILE_APPEND); die("DB Error: ". $e->getMessage()); } ?>

Displaying results


<?php
  // truncated for example purposes
  $stmt = $dbh->query('SELECT * FROM table');
  $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

foreach($results as $row) { echo $row['field1'].' '.$row['field2']; // etc... // In a users table these could be 'first_name', 'last_name', 'email' etc } ?>
PDO::FETCH_ASSOC: This tells PDO to return the rows as an associative array with the field names as keys.

Counting records


<?php
  $stmt = $dbh->query('SELECT * FROM table');
  $row_count = $stmt->rowCount();
  echo $row_count.' rows selected';
?>
PDO allows us to use rowCount() method on a PDO statement to simply count the number of records returned.

Useful when displaying how many articles to a user, or deciding whether you need to paginate results in an application, maybe

Insert


<?php
  $result = $dbh->exec("INSERT INTO table(firstname, lastname) VALUES('John', 'Doe')");
?>
You can get the last insert id by:

 $insertId = $dbh->lastInsertId();

UPdate


<?php
  $affected_rows = $dbh->exec("UPDATE table SET field='value'");
  echo $affected_rows.' were affected'
?>
Or specific rows:
<?php  $affected_rows = $dbh->exec("UPDATE table SET field='value' WHERE id='id'");
  echo $affected_rows.' were affected'
?>

Delete


<?php
  /* Delete specific rows from the USERS table */
  $del = $dbh->prepare("DELETE FROM users WHERE first_name = 'Chris'");
  $del->execute();

  /* OR */

  /* Delete all rows from the USERS table */
  $del = $dbh->prepare('DELETE FROM users');
  $del->execute();

  /* Return number of rows that were deleted */
  echo("Return number of rows that were deleted:\n");
  $count = $del->rowCount();
  echo("Deleted $count rows.\n");
?>

Statements with parameters


$stmt = $dbh->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->execute(array($id, $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  • The prepare method sends the query to the server, and it's compiled with the '?' placeholders to be used as expected arguments.
  • The execute method sends the arguments to the server and runs the compiled statement. Since the query and the dynamic parameters are sent separately, there is no way that any SQL that is in those parameters can be executed... so NO SQL INJECTION can occur! This is a much better and safer solution than concatenating strings together.

Statements with parameters


Passing parameters as an array will bind each param
as a String type by default.

You can specify the type for each param
by using 'bindValue':

$stmt = $dbh->prepare("SELECT * FROM table WHERE id=? AND name=?");
$stmt->bindValue(1, $id, PDO::PARAM_INT);
$stmt->bindValue(2, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Named parameters

If you have lots of parameters to bind, it may become confusing having lots of '?' in a statement.

PDO allows you to use named placeholders instead of the '?':
$stmt = $dbh->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
You can bind using 'execute' with an array as well:
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Insert,update,delete in action

Insert
$stmt = $dbh->prepare("INSERT INTO table(field1,field2,field3,field4,field5) VALUES(:field1,:field2,:field3,:field4,:field5)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2, ':field3' => $field3, ':field4' => $field4, ':field5' => $field5));
$affected_rows = $stmt->rowCount();
Update
$stmt = $dbh->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();
Delete
$stmt = $dbh->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();

SQL Functions

http://www.w3schools.com/sql/sql_functions.asp

SQL Aggregate Functions
SQL aggregate functions return a single value, calculated from values in a column.

  • AVG() - Returns the average value
  • COUNT() - Returns the number of rows
  • FIRST() - Returns the first value
  • LAST() - Returns the last value
  • MAX() - Returns the largest value
  • MIN() - Returns the smallest value
  • SUM() - Returns the sum

SQL Functions

SQL Scalar functions
SQL scalar functions return a single value, based on the input value.

  • UCASE() - Converts a field to upper case
  • LCASE() - Converts a field to lower case
  • MID() - Extract characters from a text field
  • LEN() - Returns the length of a text field
  • ROUND() - Rounds a numeric field to the number of decimals specified
  • NOW() - Returns the current system date and time
  • FORMAT() - Formats how a field is to be displayed

SQL Functions


You will need to use SQL Functions in the query, not as a placeholder:

This will not work:
$time = 'NOW()';
$name = 'BOB';
$stmt = $dbh->prepare("INSERT INTO table(`time`, `name`) VALUES(?, ?)");
$stmt->execute(array($time, $name));
This will:
$name = 'BOB';
$stmt = $dbh->prepare("INSERT INTO table(`time`, `name`) VALUES(NOW(), ?)");
$stmt->execute(array($name));

SQL Functions


However, you can bind arguments into SQL functions:

$name = 'BOB';
$password = 'password';
$stmt = $dbh->prepare("INSERT INTO table(`hexvalue`, `password`) VALUES(HEX(?), PASSWORD(?))");
$stmt->execute(array($name, $password));

SQL Functions


However, this does NOT work for 'LIKE':

$stmt = $dbh->prepare("SELECT field FROM table WHERE field LIKE %?%");
$stmt->bindParam(1, $search, PDO::PARAM_STR);
$stmt->execute();
Instead, use:

$stmt = $dhb->prepare("SELECT field FROM table WHERE field LIKE ?");
$stmt->bindValue(1, "%$search%", PDO::PARAM_STR);
$stmt->execute();

Executing statements in a loop


Because the sql statement gets compiled first, it can be called multiple times in a row with different arguments, and you'll get a big speed increase vs calling mysql_query over and over again!

Typically this is done by binding parameters with 'bindParam'.

bindParam is much like 'bindValue' except instead of binding the value of a variable, it binds the variable itself, so that if the variable changes, it will be read at the time of execute.

Executing statements in a loop


$values = array('bob', 'alice', 'lisa', 'john');
$name = '';
$stmt = $dbh->prepare("INSERT INTO table(`name`) VALUES(:name)");
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
foreach($values as $name) {
  $stmt->execute();
}

Transactions

  • Calling beginTransaction() turns off autocommit mode.
  • While autocommit mode is turned off, changes made to the database via the PDO object instance are not committed until you end the transaction by calling PDO::commit().
  • Calling PDO::rollBack() will roll back all changes to the database and return the connection to autocommit mode.

Transactions


try {
    $dbh->beginTransaction();
 
    $dbh->exec("SOME QUERY");
 
    $stmt = $dbh->prepare("SOME OTHER QUERY?");
    $stmt->execute(array($value));
 
    $stmt = $dbh->prepare("YET ANOTHER QUERY??");
    $stmt->execute(array($value2, $value3));
 
    $dbh->commit();
} catch(PDOException $ex) {
    //Something went wrong rollback!
    $dbh->rollBack();
    echo $ex->getMessage();
}

Ok, But how Do I create a Database?


$dbh->exec("CREATE DATABASE IF NOT EXISTS `$db`;
  CREATE USER '$user'@'localhost' IDENTIFIED BY '$pass';
  GRANT ALL ON `$db`.* TO '$user'@'localhost';
  FLUSH PRIVILEGES;")
or die(print_r($dbh->errorInfo(), true));
... and a table:
$dbh->exec("CREATE TABLE IF NOT EXISTS $table (
  first_name VARCHAR(150),
  last_name  VARCHAR(150),
  created_at VARCHAR(100)")

Copy of PDO

By juan david ramirez londoño