Transcript
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


Recommended