Without a doubt, the best way to understand the logic that stands behind a data mapper is by subclassing the previous “DataMapperAbstract” class. In this case, the goal is to map user domain objects to a single MySQL table, so it’s necessary to define a concrete user mapper class that implements the methods defined by the abstract parent. This is basically Inheritance 101, so take a look at the following file, which partially defines the user mapper class: (UserMapper.php)
<?php
class UserMapper extends DataMapperAbstract { protected $_table = 'users';
// fetch domain object by ID public function find($id) { // if the requested domain object exists in the identity map, get it from the there if (array_key_exists($id, $this->_identityMap)) { return $this->_identityMap[$id]; } // if not, get domain object from the database $this->_db->query("SELECT * FROM $this->_table WHERE id = $id"); if ($row = $this->_db->fetch()) { $user = new User; $user->id = $row->id; $user->fname = $row->fname; $user->lname = $row->lname; $user->email = $row->email; // save domain object to the identity map $this->_identityMap[$id] = $user; return $user; } }
// save domain object public function save(DomainObjectAbstract $user) { // update domain object if ($user->id !== NULL) { $this->_db->query("UPDATE $this->_table SET fname = '$user->fname', lname = '$user->lname', email = '$user->email' WHERE id = $user->id"); } // insert domain object else { $this->_db->query("INSERT INTO $this->_table (id, fname, lname, email) VALUES (NULL, '$user->fname', '$user->lname', '$user->email')"); } } } As the above file shows, building a user mapper class that retrieves, inserts and updates user domain objects is by no means rocket science. In the previous example, the mapper uses the MySQL adapter to perform the required database operations via its “query()” method, but naturally it’s possible to get the same results by using methods with a higher level of abstraction. Also, you should pay attention to the implementation of the mapper’s “find()” method, which uses an identity map to keep track of which objects were retrieved from the database. In simple terms, if the requested object exists in the map, it’s retrieved from there. Otherwise, the mapper first fetches the required data from the corresponding MySQL table, then populates a fresh user object with the data, and finally saves the object to the map. Here, it’s clear to see that an identity map not only allows you to track objects easily, but behaves like a memory-based cache that saves unnecessary trips to the database. Hopefully, at this point you’ve learned how to build a basic data mapper class that decouples user objects from their storage mechanism. In its current state, the mapper is somewhat immature, as it is only able to fetch, insert, and update objects. However, the capability for deleting objects will be added in the next tutorial, so in the meantime feel free to play with all the examples shown before. Such practice will help you to gain a better understanding of how to build data mappers in PHP. Final thoughts In this third episode of the series, I started developing a basic user mapper class, which allows you to map user domain objects to their associated database table in a fairly easy way. In its current state, this sample mapper is only capable of retrieving and saving the corresponding domain objects to the storage mechanism, which is fine for now. Nevertheless, it’d be highly desirable to provide the mapper with the ability to delete domain objects via a simple method. That’s exactly what I’m going to discuss in the next part of the series, so you won't want to miss it!
blog comments powered by Disqus |
|
|
|
|
|
|
|