Constructing the mapping layer is a two-steps process. First, it’s necessary to define a contract (pretty similar to the one used with the database adapters discussed previously), which must be satisfied by all of the mapper classes created afterward. And second, the generation of these classes will be achieved by subclassing a generic mapper, even though this last step is optional. With that said, here’s the interface that defines the structure of the aforementioned contract: (DataMapperInterface.php) <?php interface DataMapperInterface Although the definition of the above “DataMapperInterface” interface is pretty short, it’s clear to see that it declares a bunch of methods that can be used for performing CRUD operations against the data access layer. Apart from the classic finders that can be found in most mappers, like “findById()” and “findAll(),” there are a few additional methods that allow you to save and delete records associated with a specified entity. Since the role of an interface is to define a contract, and nothing else, it’s up to the mappers to concretely implement these entity-related operations. Got that? Great. Now that you understand the purpose of defining the earlier interface, the next thing that we need to do is create a class that implements the interface in question, and also encapsulates common functionality shared by concrete mapping classes. This will be done in the section below, so keep reading. Implementing the previous interface: defining a generic mapper In keeping with the concepts deployed above, the last step we must take to get the mapping layer of this sample application finished is to build a generic mapper class. For obvious reasons, this class will be declared abstract, and its initial definition will be as follows: (DataMapperAbstract.php) <?php abstract class DataMapperAbstract implements DataMapperInterface
(DataMapperException.php) <?php class DataMapperException extends Exception{} While it’s fair to admit that, at a glance, the source code of the above “DataMapperAbstract” class looks somewhat complex, this is a misleading impression. In fact, the class is a generic mapper that concentrates most of the functionality required to perform CRUD operations in a MySQL database table. It’s that simple, really. In addition, you should notice that its constructors inject two collaborators. The first one is an instance of the previous MySQL adapter, which is utilized internally for executing the aforementioned operations. The second one is an abstract collection object, which is used within the “findAll()” and “search()” methods. You're wondering where the latter comes from, right? This object is an instance of a countable, iteratable class responsible for handling collections of entities. But leave your troubles behind, at least for the moment, and don’t feel concerned about the implementation of this class; it’ll be covered in detail in upcoming tutorials in this series. Needless to say, if you test the “DataMapperAbstract” class in its current state, you’ll get an ugly fatal error; it doesn’t fully implement all of the methods declared by the “DataMapperInterface” interface. Again, fear not, as these pending methods will be added to the class and discussed in depth in the following installment. It’s safe to say, however, that the mapping layer of this sample application is near completion. It now includes a generic data mapper which can be easily subclassed to create concrete mappers, including the one responsible for handling user objects. This is a remarkable advance toward the implementation of a user repository. Final thoughts In this third episode of the series, I added to this sample application a simple mapping layer composed of a single interface and a generic mapper class. Even though the development of the latter is still incomplete, as it’s necessary to add the methods that save and delete entities, it can already be used effectively as a mediator between the domain and data access layers defined previously. As I said before, the implementation of these missing methods will be covered in the next tutorial, so if you’re interested in learning how this will be done, don’t miss the upcoming part!
blog comments powered by Disqus |
|
|
|
|
|
|
|