Building Data Mapper PHP5


Published on

See all the steps involved to build a fully functional data mapper with object-oriented PHP5 using the power and simplicity of the Standard PHP Library. Based on the early development of a new PHP DataMapper project Vance Lucas started a few months ago as the Model layer for an MVC framework.

Published in: Technology
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Building Data Mapper PHP5

  1. 2. “ A layer of mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself” Martin Fowler, Patterns of Enterprise Application Architecture
  2. 3. <ul><li>Object-Relational Mapping (ORM) </li></ul><ul><ul><li>Objects => Relational Database </li></ul></ul><ul><ul><li>Relational Database => Objects </li></ul></ul><ul><ul><li>Think “Translation layer” </li></ul></ul><ul><li>Objects have no knowledge of database or SQL </li></ul><ul><li>Database has no knowledge of objects </li></ul><ul><li>Objects have no knowledge of mapper </li></ul>
  3. 4. <ul><li>Allows you to work with native objects in your application </li></ul><ul><li>Writing SQL statements for everything in your application can be tedious </li></ul><ul><ul><li>INSERT, UPDATE especially </li></ul></ul><ul><li>Reduce time working on projects </li></ul>
  4. 5. <ul><li>Ultra Portable </li></ul><ul><ul><li>No dependencies on packages outside PHP5 </li></ul></ul><ul><li>Use standard naming conventions </li></ul><ul><ul><li>Zend/PEAR Coding Standards </li></ul></ul><ul><li>Simple, clear syntax that fits with PHP </li></ul><ul><li>Generic Usage </li></ul><ul><ul><li>Can work with any table by extending </li></ul></ul><ul><ul><li>Eliminate the need for custom SQL (in most cases) </li></ul></ul><ul><ul><li>Enable full automation wherever possible </li></ul></ul>
  5. 6. <ul><li>Row objects as “dumb” as possible </li></ul><ul><ul><li>Not tied to the data mapper </li></ul></ul><ul><li>Allow custom SQL when needed for flexibility </li></ul><ul><li>Support table relations </li></ul><ul><li>Use adapters for database independence </li></ul><ul><li>Don’t depend on too much “magic” </li></ul><ul><ul><li>No automatic discovery of tables or fields </li></ul></ul><ul><ul><li>No table or column naming schemes for relations </li></ul></ul>
  6. 7. CodeIgniter DataMapper:
  7. 8. <ul><li>What objects will we need to start? </li></ul><ul><ul><li>DataMapper </li></ul></ul><ul><ul><ul><li>Result – Individual row object </li></ul></ul></ul><ul><li>Start with DataMapper </li></ul><ul><ul><li>Define basic public interface </li></ul></ul>
  8. 10. <ul><li>What table are we working with? </li></ul><ul><li>All finders generate SQL </li></ul><ul><ul><li>They can use “findBySql” internally </li></ul></ul><ul><li>get() needs a primary key field defined </li></ul><ul><li>findFirst() can use find() with a LIMIT clause </li></ul><ul><li>save() can use insert() or update() internally </li></ul><ul><li>insert() and update() both need fields/values </li></ul><ul><ul><li>Which fields exist in the table? </li></ul></ul>
  9. 12. <ul><li>Required fields </li></ul><ul><ul><li>Built-in validation? </li></ul></ul><ul><ul><li>How do we handle errors? </li></ul></ul><ul><li>Field types </li></ul><ul><ul><li>Cast to specified type or validate automatically? </li></ul></ul><ul><li>Table relations </li></ul><ul><ul><li>How do we handle table relations? </li></ul></ul><ul><ul><li>Loading an external mapper – how? </li></ul></ul>
  10. 15. <ul><li>Finders must return FALSE or iterate </li></ul><ul><ul><li>Results must be able to be in foreach() loop </li></ul></ul><ul><li>Relations accessible by set field alias </li></ul><ul><ul><li>Implementation defined ‘contacts’ </li></ul></ul><ul><ul><li>$user->contacts should have the related fields </li></ul></ul><ul><li>Relations must also return FALSE or iterate as well as be able to be count()-ed </li></ul>
  11. 16. Eager Loading Always loads relations with row Lazy Loading Loads relations only when asked
  12. 17. <ul><li>Wait… How? </li></ul><ul><ul><li>$user->contacts can’t be an array </li></ul></ul><ul><ul><li>$user object does not know about mapper </li></ul></ul><ul><ul><ul><li>Can’t pull in relations dynamically from mapper with “__get” magic method </li></ul></ul></ul><ul><li>Are we stuck with eager loading? </li></ul>
  13. 18. <ul><ul><li>Relation Object as a placeholder empty until called </li></ul></ul><ul><li>Relation Object uses SPL interfaces </li></ul><ul><ul><li>IteratorAggregate, Countable </li></ul></ul><ul><ul><ul><li>foreach() – can iterate </li></ul></ul></ul><ul><ul><ul><li>count($user->contacts) will work </li></ul></ul></ul><ul><ul><li>Use SPL functions to fetch results upon request </li></ul></ul>
  14. 20. <ul><li>$user->contacts </li></ul><ul><li>foreach() calls ‘getIterator()’ (IteratorAggregate) </li></ul><ul><ul><li>Calls findAllRelation(), returns ResultSet object </li></ul></ul><ul><li>count() calls ‘count()’ (Countable) </li></ul><ul><ul><li>Calls findAllRelation(), returns count of found rows </li></ul></ul><ul><li>findAllRelation() calls findAll(), caches result </li></ul><ul><ul><li>findAll() gets related rows from related mapper with given foreign keys as conditions </li></ul></ul>
  15. 23. <ul><li>Adapters </li></ul><ul><ul><li>Adapter Interface </li></ul></ul><ul><ul><li>One Initial adapter to test with </li></ul></ul><ul><ul><ul><li>Adapter_PDO_MySQL </li></ul></ul></ul><ul><li>Relations </li></ul><ul><ul><li>Relation Interface </li></ul></ul><ul><ul><li>Relation_HasMany </li></ul></ul>
  16. 24. <ul><li>PHPDataMapper </li></ul><ul><ul><li>_Database </li></ul></ul><ul><ul><ul><li>_Adapter </li></ul></ul></ul><ul><ul><ul><ul><li>_PDO </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>_Mysql </li></ul></ul></ul></ul></ul><ul><ul><li>_Exception </li></ul></ul><ul><ul><li>_Model </li></ul></ul><ul><ul><ul><li>_Relation </li></ul></ul></ul><ul><ul><ul><ul><li>_HasMany </li></ul></ul></ul></ul><ul><ul><ul><li>_ResultSet </li></ul></ul></ul><ul><ul><ul><li>_Result </li></ul></ul></ul>
  17. 25. <ul><li>Why not a generic ‘stdClass’ or an array? </li></ul><ul><li>A Result object lets us: </li></ul><ul><ul><li>Keep track of changed fields for update() </li></ul></ul><ul><ul><li>Use object syntax – $row->name; </li></ul></ul><ul><ul><ul><li>Suppress undefined property errors with __get() </li></ul></ul></ul><ul><ul><li>Use array syntax – $row[‘name’]; </li></ul></ul><ul><ul><ul><li>SPL ArrayAccess interface </li></ul></ul></ul><ul><ul><ul><li>Suppress undefined index errors with offsetGet() </li></ul></ul></ul><ul><ul><li>Use getter functions - $row->getName(); </li></ul></ul><ul><ul><ul><li>Automatic functions for all fields with __call() </li></ul></ul></ul>
  18. 29. <ul><li>Simple syntax to get almost any record </li></ul><ul><li>All results returned are “live” objects </li></ul><ul><ul><li>Can be altered and saved at any time </li></ul></ul><ul><li>No writing SQL code for mundane operations </li></ul><ul><li>Promotes good programming style </li></ul><ul><ul><li>Easier to always use mapper object than write SQL queries all over the place </li></ul></ul>
  19. 30. <ul><li>Project Page on my blog </li></ul><ul><ul><li> </li></ul></ul><ul><li>Open-Source Project </li></ul><ul><ul><li>MIT License </li></ul></ul><ul><ul><li>On Google Code </li></ul></ul><ul><li>Martin Fowler’s “P of EAA” </li></ul><ul><ul><li> </li></ul></ul>
  20. 31. <ul><li>Vance Lucas, 23 </li></ul><ul><ul><li>Blog: </li></ul></ul><ul><ul><li>Email: [email_address] </li></ul></ul><ul><li>Making websites since age 12 </li></ul><ul><ul><li>Started learning PHP when PHP3 was new </li></ul></ul><ul><li>Oklahoma Baptist University – Shawee </li></ul><ul><ul><li>Bachelor of Business Administration </li></ul></ul><ul><li>Currently work at Back40Design, Inc. </li></ul><ul><ul><li> </li></ul></ul>