I am working on a project and have been asked to make both Data Access Objects and Data Mapper Classes.

I'm familiar with the idea of a data access class for each table - we have a property for each field in the table, we have insert/update/delete/get methods.

What I'm confused about is the Data Mapper Class concept. The spec I'm looking at implies that it's the Data Mapper classes that are supposed to support the insert/update/delete methods.

This is no doubt some programming dogma from a book I haven't read. Can anyone explain to me this Data Mapper concept?

    The spec I'm looking at implies that it's the Data Mapper classes that are supposed to support the insert/update/delete methods.

    Exactly. The data object itself doesn't know how to store or update itself, so it could be presisted in a session, in a file, in a database or over the wire I guess. But it doesn't know or care. The DataMapper does the dirty work of actually save/find/delete (save = insert or update). To do this the DataMapper is going to peek at the vars of the data object...probably breaking encapsulation 🙂. The Mapper depends on the data object class, but the data object should know nothing about the mapper.

    http://martinfowler.com/eaaCatalog/dataMapper.html

      Thanks for your response!

      Unfortunately, your link is a bit light on the details. In particular, it doesn't have any code examples to better spell out exactly what the distinction is here. Does that mean I have to buy the book? I'm wondering what kind of rewards might be in store for this tedious extra step.

      I've been googling for DataMapper, 'data mapper', etc. and I see your link in there among a bunch of other branded frameworks and such. I'm getting the feeling this is the same sort of thinking that gets people using frameworks. The idea of an abstraction layer between my objects in the DB make me feel like I'm destined for some extra work with little reward.

        FWIW, the book is really eye-opening. But Martin also says he would recommend you "purchase" a data mapping layer rather than code your own...but you can do simple stuff...but if its so simple then an ActiveRecord is a better choice...and hence ruby, cake, etc, all seem to use ActiveRecord.

        The best "mapper" I've seen for php was Doctrine ([url]http://www.phpdoctrine.org)[/url], but I found it difficult to use because the phpdoc API is wrong in places, making using the classes impossible; and I generated the php api from the Doctrine sources directly. That said, my own phpdoc comments are probably not 100% accurate, as it really requires another set of eyes to verify everything is correct.

        Really, although a code sample is nice, if you have the "interface" you can probably fill in the blanks:

        function insert($data_obj)
        {
        // create and execute SQL to write $data_obj to DB, which is simple if
        // $data_obj maps to a single table
        }
        

        And I would add finder methods to the mapper as well

        function find($id)
        {
        // extract, construct and return instance of data object with ID $id
        }
        
        function find_where($where)
        {
        // now it gets trickly...pear and PDO (same thing?) have some interesting approaches
        // but I prefer to make $where be an assoc. array of column names => values
        // so $where = array('username'=>'Bill Gates') makes an SQL statement
        // with a where clause: "WHERE `username` = 'Bill Gates'
        }
        

        I've done this, sort of, and you can see the PHP5 code here in the DB package look at DAO and DTO classes:

        http://phpfunk.com/software/api/

        There is some "cruft" in my code, but it does work. That is, I originally had the class work one way (try to use a table naming convention to map tables to object classes) but that didn't last too long, so now the DAO takes the name of the class and the table name as constructor parameters.

          I checked your link (i love phpDocumentor!) but was unable to find any classes named DAO or DTO.

          My curiosity here is in 2 parts
          1) How
          If I have a simple class that has a property for each column in my table (can we call this the DAO?), how does this object connect to the MAP class? Does DAO extend MAP or vice versa? Is a DAO instance a property of the MAP instance or vice versa? I'm imagining that a MAP class might have an insert() method that refers to one of its properties

          class MAP_Item {
            function insert() {
              $sql = "INSERT INTO Item (field1, field2, field3) VALUES (
                  " . $this->item->field1 . ",
                  " . $this->item->field2 . ",
                  " . $this->item->field3;
              // blah blah blah
            }
          }
          

          But that's really all I've imagined as of yet. I'm sort of wondering how these DAO and MAP classes play together.

          2) Why??
          This is a much bigger question to me. So far the only reason I can come up with to create this extra layer of abstraction is so that I might switch from a DMBS to some totally different persistence mechanism like flat files or perhaps some kind of socket communication. I just can't think of any other situation that would justify the extra work of abstracting a DAO from the persistence mechanism. I've found that PEAR::MDB2 is perfectly useful for an abstraction layer and helps me build db-independent code. I'm having a hard time imagining the circumstances that would justify all this extra effort.

          Don't get me wrong, though. I do like the idea of data abstraction...I realize it's necessary for the internet to develop sentience on its way to becoming our one true master.

            You are so right on w/ your idea (your insert method). The data class has simple properties and the mapper reaches into the data class (ala $data_object->field1) and creates SQL. The mapper knows which columns in which table(s) go w/ which fields in the data object class.

            The object being mapped knows nothing about the mapper.

            And the mapper doesn't save necessarily to a database...it abstracts the find/save/delete so it can happen...well however it needs to happen (typically database).

            RE switching database vendors:
            If you know mssql, postgresql and mysql you know that the sql statements themselves are different enough at times that pear DB and the like won't help you; You need a QueryBuilder similar to what php Doctrine has.

            My links....My class naming is horrible...the code got refactored over time but the names never got fixed:
            http://phpfunk.com/software/api/DB/PhpFunk_DB_DAO.html
            http://phpfunk.com/software/api/DB/PhpFunk_DB_DTO.html <-- the data object

            I'm using the naming style: vendor-package-class hence the PhpFunk_DB_DAO class.

            $dao->save($dto);
            $dto = &$dao->find($id);
            etc...

            Unfortunately its my bed time now so I gotta run...6:00 AM comes way too soon.

              OK...I think I'm starting to understand. My 'MAP' concept is the same as your DAO. My DAO is the same as your DTO. I believe that in common usage these are defined thusly:

              Data Transfer Object (DTO) is a super-simple class consisting only of properties and possibly set/get methods for those properties. If my persistence mechanism is a database, the properties of this class will probably have a one-to-one correspondence with the fields of the db table.

              Data Access Object (DAO) is the mapper class I was attempting to describe. According to this description of DTOs from sun, the DAO (referred to as a BusinessObject) "is responsible for creating the [DTO] and returning it to the client upon request" and "may also receive data from the [application] in the form of a [DTO] and use that data to perform an update".

              Perhaps wrongly, I was imagining the reverse. I had envisioned an application that talks to a DTO with persistence techniques handled by a DAO member object:

              $item = new Item(); // instantiate the DTO
              $item->useDB(); // sets the persistence mechanism to use a particular DAO
                              // sort of like saying $item->persistenceMech = new DAO_Item_DB($params);
              $item->fetch($id);
              $item->itemify('foobar');
              $item->save();
              

              I'm having a bit of difficulty picturing the difference this would make in code. My first thoughts are that I should perhaps avoid big nasty DAO objects appended to every single DTO. Is it more useful/correct to think of a shepherd herding sheep or to think of every sheep having a reference to a shepherd?

              I am digging the code kung-fu in your DAO class. I especially like the
              economy of the insert function:

                  function _insert(&$dto)
                  {
                      $vars = $dto->_get_vars();
                      $sql = "insert into {$this->_table} set ";
                      $var_strs = array();
                      foreach($vars as $v) {  
              $var_strs[] = "$v='" . $this->_conn->escape($dto->{$v}) . "'"; } $sql .= implode(", ", $var_strs); $res = $this->_conn->execute($sql); if($res === FALSE) return FALSE; $dto->{$this->_pkey} = $this->_conn->lastInsertID(); return $res; }

              I'm imagining this DAO can apply to almost any DTO so you don't have to keep writing it over and over again. Is that the case?

                Another thing occurred to me. This DAO class would not support a JOIN between two tables or a 'select max(id) blah blah' sort of query. Where might those live?

                  I'm imagining this DAO can apply to almost any DTO so you don't have to keep writing it over and over again. Is that the case?

                  You are correct. On a couple rare occasions I've subclassed the DAO, typically becuase I needed some special "find" methods.

                  Another thing occurred to me. This DAO class would not support a JOIN between two tables or a 'select max(id) blah blah' sort of query. Where might those live?

                  Now you're getting into the mire that is object-relational mapping (ORM)...by its very design the DTO/DAO system cannot span multiple tables. Its the same w/ ActiveRecord too. Hence the need for a mapper class! Again, if you're really interested in exploring this the PEAA book by Martin Fowler has several chapters on ORM.

                  This looks somewhat promissing but I've not had the chance to explore it:
                  http://propel.phpdb.org/trac/

                  These days I'm more intested in using off the shelf components to build applications.

                    21 days later

                    That propel thing seems interesting to me. I have considered writing my own code which would take a database and
                    1) run an EXPLAIN query to extract info about the database
                    2) automatically generate an input form after the user selects a couple of options
                    3) generate a form handler script to handle submissions from the form
                    4) generate classes which would simplify interactions with the db table to be used elsewhere in my code

                    It sounds like that may be what propel is doing. I found this interesting:
                    "Migrating an application that uses Propel from one RDBMS to another is a simple configuration value change."
                    Having seen the difference between MySQL and Postgres, I'm not sure I believe that.

                    I have written my own DAO and DTO classes similar to that one you showed me but I am now wondering where one should put validation? You can't apply the same validation to all forms using the DAO. I typically put validation in my object classes for a datatable object so I don't need to re-write the validation code for every form that deals with a particular data table (i.e., put validation as close as possible to the db table itself). Where do you typically put your input validation?

                      OO in PHP is kinda lacking in some places, and its a performance hit. Imagine having lots of layers of OO that work together...makes for slow PHP apps, so keep it simple, eh?

                      Don't do validation in the data access layer...not form validation...its sole purpose is to move things into/out of RDBMS. Put form validation in the application layer.

                      I kinda see it like this:

                      presentation layer
                      application layer
                      business layer
                      object-relationtional mapping layer (dao/dto)
                      database abstraction layer (i have a DBWrapper class, php5 has pdo?)
                      the database (mysql, etc)

                        Write a Reply...