Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Object Relational Mapping in PHP

70,181 views

Published on

"Object Relational Mapping in PHP"

Presentation given to PHPNW on 05/05/09 by Rob Knight

Published in: Technology

Object Relational Mapping in PHP

  1. 1. Object-Relational Mapping in PHP PHPNW May 2009 Rob Knight - Lead Technical Architect, PRWD http://robknight.org.uk
  2. 2. What is ORM? • Manages the translation of objects into relational databases, and vice-versa • Most modern programming languages, including PHP, have a concept of objects • Most databases, including MySQL, Oracle and Postgresql are relational
  3. 3. Objects • Classes define the blueprint • Classes can inherit from each other • Objects contain data and methods • Object data can include other objects and arrays/lists
  4. 4. A very simple class <?php class Employee extends Person { protected $salary; // floating-point value protected $contractLength; // integer value protected $manager; // reference to another Employee object protected $skills; // array of 'Skill' objects protected $history; // array of 'History' objects protected $id; // unique identifier }
  5. 5. Relational Databases • Basic unit of storage is the table • Tables can only contain simple data types (numbers, strings, binary data) • No concept of arrays or lists • Tables can be related by foreign keys
  6. 6. A simple table id name salary manager_id contract_length 1 Alice 20000.00 2 12 2 Bob 150000.00 NULL NULL 3 Clive 15000.00 5 6 4 Derek 32000.00 2 NULL 5 Edith 45000.00 2 NULL
  7. 7. Advantages of ORM • Everything in PHP • In theory, no need to understand the underlying data storage system • ORM can make it easy to adopt good patterns and good database design • Enables familiar OO concepts for manipulating data
  8. 8. Use of PHP concepts <?php $employee = new Employee(); // use of object-oriented concepts $employee->setName(‘Joe’); $employee->save(); // underlying database could by MySQL, SQLite, Postgres or Oracle $peopleToFire = EmployeeTable::select(‘id’)->where(‘salary < 20000’) ->andWhere(‘relatedToChairman = 0’)->limit(5); $subordinates = EmployeeTable::select(‘*’)->where(‘manager_id = ?’, $manager->id); // automatic variable escaping ?>
  9. 9. Disadvantages of ORM • The extra layer of abstraction can be a performance hit • Can be verbose • OO isn’t always best • Can be inflexible • Sometimes framework-dependent
  10. 10. ORM can be verbose Using Propel $c = new Criteria(); $cton1 = $c->getNewCriterion(ArticlePeer::TITLE, '%FooBar%', Criteria::LIKE); $cton1 = $c->getNewCriterion(ArticlePeer::SUMMARY, '%FooBar%', Criteria::LIKE); $cton1->addOr($cton2); $c->add($cton1); $c->add(ArticlePeer::PUBLISHED_AT, $begin, Criteria::GREATER_THAN); $c->addAnd(ArticlePeer::PUBLISHED_AT, $end, Criteria::LESS_THAN); $article = ArticlePeer::doSelect($c); SQL Query SELECT * FROM article WHERE (title LIKE ‘%FooBar%’ OR summary LIKE ‘%FooBar’) AND published_at > {$begin} AND published_at < {$end}
  11. 11. There are many ORMs • Doctrine <http://www.doctrine-project.org> • Propel<http://propel.phpdb.org> • Zend_Db <http://framework.zend.com/manual/en/zend.db.html> • Kohana ORM <http://docs.kohanaphp.com/libraries/orm> • PDO <http://www.php.net/pdo>
  12. 12. ORM Patterns From ‘Patterns of Enterprise Application Architecture’ - Martin Fowler, 2003 • Table Data Gateway Zend_Db_Table, Propel ‘Peer’ classes • Row Data Gateway Zend_Db_Table_Row • Data Mapper • Active Record Doctrine_Record, Propel classes
  13. 13. Table Data Gateway • One class per table • Basic functions for inserting, updating, deleting data from the table • Can also handle related tables • Data is returned in simple array/POPO form
  14. 14. An example <?php // Using Zend_Db_Table to fetch a record from a table class BlogPostTable extends Zend_Db_Table_Abstract { ... } $table = new BlogPostTable(); $select = $table->select()->where(‘author_id = ?’, $id)->order(‘created DESC’); $row = $table->fetchRow($select); // row is an array, with keys for column names echo $row->title; // prints the title of the blog post ?>
  15. 15. Row Data Gateway • Class for manipulating a single row • Separates finding/searching from manipulation • Database access logic only
  16. 16. An example <?php // create row using table object $table = new BlogPostTable(); $newRow = $table->createRow(); // set values $newRow->title = ‘New Blog Post’; $newRow->body = ‘Lorem ipsum....’; // save the row to the table $newRow->save(); ?>
  17. 17. Active Record • Similar to Row Data Gateway • Classes inherit from a ‘Record’ class • Classes may also implement ‘behaviours’ • Some mixing of data storage code and domain logic
  18. 18. An example <?php class User extends Doctrine_Record { public function setTableDefinition() { $this->hasColumn('username', 'string', 255); $this->hasColumn('password', 'string', 255); } public function authenticate($username, $password) { return ($this->username == $username) && ($this->password == $password); } } $table = Doctrine::getTable(‘User’); $user = $table->find($id); if ($user->authenticate($username, $password)) { print “Authenticated as user id {$id}”; }
  19. 19. Data Mapper • Takes your object model and saves it to database • Mapper is external to your classes • Good separation of concerns, keeps the OO away from the data • Hard to implement as a ‘drop-in’ system
  20. 20. Extras • Schema management • Auto-creation of forms, admin areas • Database creation and migration • Plugins and behaviours
  21. 21. Schemas User: tableName: users columns: id: type: integer(4) primary: true autoincrement: true unsigned: true forename: type: string(50) surname: type: string(50) email: type: string(50) password: type: string(32) actAs: Timestampable: created: name: created type: integer options: unsigned: true
  22. 22. Plugins • Logging • Profiling • Behaviours - timestampable, sluggable and more • Events • Inheritance • Caching
  23. 23. Performance Issues • Joins Complex relationships between objects can lead to inefficient joins between tables • ‘Hydration’ Transforming database rows into full PHP objects can be expensive • Many classes, many files Loading many auto-generated classes can cause performance issues
  24. 24. Alternatives • Object databases • Document databases • Key-value stores • Hybrids
  25. 25. Object and Document Databases • Persevere Stores JavaScript/JSON objects • CouchDB Stores documents in JSON format • Abdera Stores documents using the Atom Publishing Protocol
  26. 26. Key-value stores • SimpleDB • BigTable • Mnesia
  27. 27. JSON: a better fit? employees: [ { name: “Alice”, salary: 35000.00, skills: [ “C++”, “PHP”, “SQL” ] }, { name: “Bob”, salary: 24000.00, skills: [ “Java”, “C#” ] } ] Might JSON object storage be better for PHP?
  28. 28. Conclusions • Choose your ORM library carefully • Experiment • Don’t over-complicate • Maybe ORM is the wrong choice anyway? • Alternatives are starting to become viable
  29. 29. Thanks for listening Any questions? Slides available at http://robknight.org.uk/presentations

×