75

The History of PHPersistence

Embed Size (px)

DESCRIPTION

Persistence is one of the most important part in a PHP project. Persisting data to a database came with PHP/FI and its MySQL support. From native extensions and PHP4 database abstraction libraries to PDO and modern ORM frameworks, you will (re)discover how persistence has evolved during the last decade. This talk will also introduce the future of data persistence with the growing success of alternative storage engines.

Citation preview

Page 1: The History of PHPersistence
Page 2: The History of PHPersistence

The History of PHPersistence

Hugo Hamon - @hhamon OSIDays November 2011

Page 3: The History of PHPersistence

PHP/FI

Where Everything Begins…

Page 4: The History of PHPersistence

1995

PHP/FI

Page 5: The History of PHPersistence

1995

Files handling

Page 6: The History of PHPersistence

$fp = fopen("/counter.txt","w+");$counter = fgets($fp,1024);$counter++;fputs($fp, $counter);fclose($fp);  

Page 7: The History of PHPersistence

1995

Databases support

Page 8: The History of PHPersistence

$db = mysql_connect("localhost", "root", "secret"); $name = "bob"; $result = mysql( $db, "select * from table where firstname='$name'" ); $num = mysql_numrows($result); echo "$num records found!<p>";

Page 9: The History of PHPersistence

$i=0; while ($i<$num); echo mysql_result($result,$i,"lcase(fullname)"); echo "\n"; echo mysql_result($result,$i,"address"); echo "\n"; $i++; endwhile;

Page 10: The History of PHPersistence

PHP 3/4

Code Reusability

Page 11: The History of PHPersistence

User Functions

Page 12: The History of PHPersistence

function db_connect($database, $host, $user, $pwd); function db_fetch_single($dbh, $query); function db_fetch_all($dbh, $query); function db_insert($dbh, $table, $values); function db_update($dbh, $table, $values, $pk); function db_delete($dbh, $table, $pk); function db_list_fields($dbh, $table); function db_drop_table($dbh, $table);

Page 13: The History of PHPersistence

function db_connect($database, $host, $user, $pwd) { $dbh = mysql_connect($host, $user, $pwd); if (!$dbh) { die('Server unavailable: '. mysql_error()); } if (!mysql_select_db($database, $dbh)) { die("'$database' unavailable: ". mysql_error()); } return $dbh; }

Page 14: The History of PHPersistence

/** * Fetches a single record from a database * * @param resource $dbh The database handler * @param string $query A SQL query * @return array A single record as an array */ function db_fetch_single($dbh, $query) { return current(db_fetch_all($dbh, $query)); }

Page 15: The History of PHPersistence

function db_fetch_all($dbh, $query) { $result = mysql_query($query, $dbh); if (!$result) { die('Invalid query: '. mysql_error()); } $records = array(); while ($record = mysql_fetch_assoc($result)) { $records[] = $record; } return $records; }

Page 16: The History of PHPersistence

function db_insert($dbh, $table, array $values) { $data = array(); foreach ($values as $value) { $data[] = mysql_real_escape_string($value, $dbh); } $sql = sprintf("INSERT INTO `$table` (`%s`) VALUES ('%s')", implode('`, `', array_keys($values)), implode("', '", $data) ); $result = mysql_query($query, $dbh); if (!$result) { die('Invalid data to insert: '. mysql_error()); } return mysql_insert_id($dbh); }

Page 17: The History of PHPersistence

include 'lib/database.inc.php'; $dbh = db_connect('osidays'); $query = 'SELECT id, name FROM author'; $authors = db_fetch_all($dbh, $query); $author = db_fetch_single( $dbh, 'SELECT id, name FROM author WHERE id = 3' ); $id = db_insert($dbh, 'author', array( 'name' => 'Jules Verne' ));

Page 18: The History of PHPersistence

PHP 4

OOP & Reusability

Page 19: The History of PHPersistence

class Database { function Database($database, host, $user, $pwd); function disconnect(); function connect(); function free(); function getErrorMessage(); function getErrorCode(); function getLastInsertId(); function insert($table, array $values); function fetchAll($query); function fetchSingle($query); function query($query); function quote($string); function hasError(); function _collectError(); function _init(); }

Page 20: The History of PHPersistence

require 'lib/Database.php'; $db= &new Database('demo', 'localhost', 'root'); $q = 'SELECT id, name FROM author'; foreach ($db->fetchAll($q) as $author) { // ... } $db->free(); $db->disconnect();

Page 21: The History of PHPersistence

require 'lib/Database.php'; $db= &new Database('demo', 'localhost', 'root'); $q = 'SELECT id, name FROM author WHERE id = 1'; $author = $db->fetchSingle($q); $db->free(); $db->disconnect();

Page 22: The History of PHPersistence

require 'lib/Database.php'; $db= &new Database('demo', 'localhost', 'root'); $res = $db->insert('author', array( 'name' => 'Jules Vernes' )); if ($result) { $id = $db->getLastInsertId(); } $db->disconnect();

Page 23: The History of PHPersistence

PHP 4

Professional APIs

Page 24: The History of PHPersistence

DBAL

Page 25: The History of PHPersistence

•  PEAR::DB

•  ADOdb

•  Metabase

•  MDB

•  MDB2

•  Creole

Page 26: The History of PHPersistence

§  Multiple databases support

§  Uni!ed APIs

§  Prepared statements supports

§  Query caching

§  Security against SQL Injections

Page 27: The History of PHPersistence

PEAR MDB2

Page 28: The History of PHPersistence

$dsn = array( 'phptype' => 'mysql', 'username' => 'root', 'password' => '', 'hostspec' => 'localhost', 'database' => 'demo', ); $db = & MDB2::connect($dsn); $db->setFetchMode(MDB2_FETCHMODE_ASSOC); $rs = $db->queryAll('SELECT id, name FROM author'); $db->disconnect();

Page 29: The History of PHPersistence

ADOdb

Page 30: The History of PHPersistence

include('adodb.inc.php'); $db = NewADOConnection('mysql'); $db->Connect('localhost', 'root', 'password', 'demo'); $result = $db->Execute('SELECT id, name FROM author'); if ($result) { while (!$result->EOF) { echo 'ID: ', $result->fields[0] ,"\n"; echo 'Name:', $result->fields[1] ,"\n";

$result->MoveNext(); } }

Page 31: The History of PHPersistence

2004

PHP 5

Page 32: The History of PHPersistence

2005

PHP Data Object

Page 33: The History of PHPersistence

•  PECL extension as of PHP 5.0.0

•  Core extension since PHP 5.1.0 (11/2005)

•  12 official drivers as of today

•  Extensible Object Oriented API

•  Prepared statements & transaction support

•  Stored procedures support

Page 34: The History of PHPersistence
Page 35: The History of PHPersistence

« PDO provides a data-access abstraction

layer, which means that, regardless of

which database you're using, you use the

same functions to issue queries and fetch

data. »

Page 36: The History of PHPersistence

« PDO does not provide a

database abstraction as it

doesn't rewrite SQL or emulate

missing features »

Page 37: The History of PHPersistence

Transactions /

Prepared Statements

Page 38: The History of PHPersistence

try { $pdo->beginTransaction(); $query = 'INSERT INTO author (name) VALUES (?)'; $stmt = $pdo->prepare($query); $stmt->bindValue(1, 'Jules Verne'); $stmt->execute(); $id = $pdo->lastInsertId(); $pdo->commit(); } catch (PDOException $e) { $pdo->rollback(); }

Page 39: The History of PHPersistence

Stored Procedures

Page 40: The History of PHPersistence

DELIMITER | CREATE PROCEDURE coming_events (IN start DATE, OUT events INT) BEGIN SELECT COUNT(*) INTO events FROM events WHERE start_at >= start; END |

$query = "CALL coming_events('2011-03-01', @events);"; $pdo->query($query); $stmt = $pdo->query("SELECT @events;"); echo $stmt->fetchColumn() ,' events to come.';

Page 41: The History of PHPersistence

PHP 5

Zend_Db

Page 42: The History of PHPersistence

Table Data Gateway

Page 43: The History of PHPersistence

class AuthorGateway extends Zend_Db_Table_Abstract { protected $_name = 'authors'; protected $_primary = 'author_id'; }

Page 44: The History of PHPersistence

$data = array( 'first_name' => 'Jules', 'last_name' => 'Vernes', ); $table = new AuthorGateway(); $table->insert($data);

Page 45: The History of PHPersistence

Row Data Gateway

Page 46: The History of PHPersistence

$table = new AuthorGateway(); // New empty row $row = $table->createRow(); // Insert a new row $row->firstName = 'Jules'; $row->lastName = 'Verne'; $row->save();

Page 47: The History of PHPersistence

Active Query

Page 48: The History of PHPersistence

$isbn = '1234567890'; $rows = $db->select() ->from(array('b' => 'books')) ->where('b.isbn = ?', $isbn) ->order(array('b.title ASC')) ->query() ->fetchAll() ;

Page 49: The History of PHPersistence

PHP 5

Object Relational Mapping

Page 50: The History of PHPersistence

•  Use objects instead of raw SQL queries

•  Database abstraction layer (not always)

•  Relationships support

•  Behaviors support (i18n, timestampable…)

•  Querying API

•  Error logging

Page 51: The History of PHPersistence

2005

Propel ORM

Page 52: The History of PHPersistence

$author = new Author(); $author->setFirstName("Leo"); $author->setLastName("Tolstoy"); $book = new Book(); $book->setTitle("War & Peace"); $book->setIsbn("0140444173"); $book->setAuthor($author); $book->save();

Page 53: The History of PHPersistence

$query = BookQuery::create() ->joinWith('Book.Author') ->joinWith('Book.Publisher') ->where('Author.firstName = ?', 'Leo') ->where('Author.lastName = ?', 'Tolstoï') ->orderByTitle() ->filterByPublishYear(2009) ->find() ;

Page 54: The History of PHPersistence

2009

Doctrine 1.x

Page 55: The History of PHPersistence

$books = Doctrine_Query::create() ->select('b.*, a.*, p.*') ->from('Book b') ->leftJoin('b.Author a') ->leftJoin('b.Publisher p') ->where('a.firstName = ?', 'Karl') ->andWhere('a.lastName = ?', 'Marx') ->orderBy('b.title ASC') ->execute() ;

Page 56: The History of PHPersistence

2009    

PHP  5.3  

Page 57: The History of PHPersistence

ORM Frameworks

Page 58: The History of PHPersistence

Doctrine2

Page 59: The History of PHPersistence

•  Database Abstraction Layer

•  Object Relational Mapping

•  Schema management

•  Migrations support

•  XML & NoSQL databases support

Page 60: The History of PHPersistence

/** @Entity() */ class Author { /** * @Id() * @GeneratedValue() * @Column(type="integer") */ private $id; /** @Column(type="string", length="30") */ private $name; /** @ReferenceMany(targetDocument="BlogPost") */ private $posts = array(); }

Page 61: The History of PHPersistence

$post = new BlogPost(); $post->setTitle('My First Blog Post'); $post->setBody('Some content...'); $author = new Author(); $author->setName('Hugo Hamon'); $author->addPost($post); $em->persist($user); $em->persist($post); $dm->flush();

Page 62: The History of PHPersistence

Toward NoSQL…

Page 63: The History of PHPersistence

«  Not  Only  SQL  »  

Page 64: The History of PHPersistence

abcdef   Hugo  Hamon  Key Value

Page 65: The History of PHPersistence

FirstName:  Hugo  

LastName:  Hamon  

Role:  Speaker  

abcdef  Key

Column 1

Column 2

Column 3

Page 66: The History of PHPersistence

Name:  Hugo  Hamon  

Role:  Speaker  

abcdef  

Skills  

0:  PHP  

1:  HTML  

2:  CSS  

Key Document

Page 67: The History of PHPersistence

2009

MongoDB Driver

Page 68: The History of PHPersistence

•  Cross-platform support

•  Schemaless language

•  BSON type support

•  Binary !le storage support (GridFS)

•  Master – slave replication support

•  Sharding (horizontal scaling)

Page 69: The History of PHPersistence

$mongo = new Mongo(); $col = $mongo->selectDb('osidays')->books; $books = array( array('title' => 'Da Vinci Code'), array('title' => 'The Lost Symbol'), array('title' => 'Digital Fortress'), ); foreach ($books as $book) { $collection->insert($book); }

Page 70: The History of PHPersistence

What’s next… … for today and tomorrow?

Page 71: The History of PHPersistence

2011

PHP 5.3 ODM Frameworks

Page 72: The History of PHPersistence
Page 73: The History of PHPersistence

•  ORM Layers for Mongodb

•  Dealing with objects instead of arrays

•  Relationships support

•  Query abstraction

•  GridFS support

•  Query logging & caching

Page 74: The History of PHPersistence

$post = new BlogPost(); $post->setTitle('My First Blog Post'); $post->setBody('Some content...'); $author = new Author(); $author->setName('Hugo Hamon'); $author->setEmail('[email protected]'); $dm->persist($user); $user->addPost($post); $dm->flush();

Page 75: The History of PHPersistence

QuesAons?  

92-98, boulevard Victor Hugo

92 115 Clichy Cedex

[email protected] (+33 (0)1 40 99 82 11)

sensiolabs.com - symfony.com – trainings.sensiolabs.com