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.

Building Data Mapper PHP5

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.

  • Login to see the comments

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>