As with many other aspects of OOP, there are several ways to create proxies that lazy-load data from the persistence layer. In this case, though, I’m going to following an approach similar to the one taken by Ben Scholzen, which uses a specific mapper to get a collection of domain objects on request. On the other hand, my own take is a bit more extendable. It makes the proxy class an implementer of the following interface: (MyApp/Common/LoadableInterface.php) <?php namespace MyApp\Common; interface LoadableInterface Having such a generic contract at our disposal, it’s really simple to create different proxy classes that lazy-load data from storage, as long as they implement the “LoadableInterface.” But, since I want to enable the blog to lazy-load single entities and collections, the next step is to define an abstract proxy that encapsulates common functionality for both use cases. The following class does precisely that: (MyApp/Common/AbstractProxy.php) <?php namespace MyApp\Common; abstract class AbstractProxy Given that this abstract proxy injects a mapper into the constructor, along with the corresponding arguments, building a concrete proxy that lazy-loads a single entity from the persistence layer is this simple: (MyApp/Common/EntityProxy.php) <?php namespace MyApp\Common; class EntityProxy extends AbstractProxy implements LoadableInterface As you can see, the “EntityProxy” class uses the “findById()” method of the injected mapper (remember that one?) to fetch an entity from the database. Of course, this process is executed whenever its “load()” method is invoked, which allows it to easily fetch a single domain object on request. Pretty good, isn’t it? What’s more, if you found it easy to understand how the earlier proxy class does its thing, be sure to check the following one. It performs a similar task with a collection of entities: (MyApp/Common/CollectionProxy.php) <?php namespace MyApp\Common; class CollectionProxy extends AbstractProxy implements LoadableInterface, \Countable, \IteratorAggregate There you have it. As you can see, the above “CollectionProxy” class uses the “find()” method of the injected mapper to lazy-load a collection of domain objects from storage. This process can be explicitly triggered either by calling the class’s “load()” method, or transparently when an instance of the class is used within a “foreach” construct (or when counting the elements stored in the collection). So far, so good. At this point, you should have a clearer idea of how to the implementation of a couple of proxy classes can help improve the way that a domain model is persisted. But, before you see these classes into action, it’s necessary to add other components to the blog, including a module that handles views. This is exactly what I’ll be doing in the following section. Defining the blog’s landing page: building a view class Since I want to keep the blog’s source code clear and easy to follow, the layer responsible for manipulating views will be simple. It will be composed of only a single class and an HTML template containing interspersed PHP code. If you want to see this view handling class, check it below: (MyApp/Views/View.php) <?php namespace MyApp\Views; class View /** /** /** /** /** /** /** /** /** Even though the definition of this view class is somewhat lengthy, its driving logic can be grasped quickly. Simply put, the class behaves like a data holder that assigns, removes and gets fields from spawned view objects, which are in turn rendered inside a specified template file. It's that simple. Since my purpose here is to show how to use the earlier proxy classes to lazy-load the comments corresponding to a particular blog entry (insertions, updates and deletions will be omitted for the sake of brevity), this is the template file that I’ll be using later on to accomplish this: (MyApp/Views/Templates/entries.php) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Although the above template file is pretty trivial -- it only contains some CSS along with a few chunks of PHP code -- it shows how blog entries will be displayed on the browser, and most importantly, how the associated comments will be transparently pulled from the database on request. Moreover, if you go back and check the implementation of the collection proxy class, you’ll recall that it fetches the pertinent comments when its “load()” method is called within a “foreach” loop (due to the implementation of the “IteratorAggregate” SPL interface). Well, that’s exactly what the template does! With that said, are you starting to see a bit more clearly how all of the pieces that compose the blog’s structure will fit together? I'm sure you do. Nevertheless, there are still some additional components that need to be constructed first, to get a fully-functional version of the blog. These will be implemented in the last tutorial. Final Thoughts In this penultimate chapter of the tutorial, I added to the existing structure of this sample blog program a host of useful components, including the classes that handle collections of entities and views, and most importantly, the ones responsible for lazy-loading domain objects from the database. Despite of all these goodies, we haven't finished developing the program yet. It's necessary to encapsulate the interaction of mappers, collections and proxies behind a simpler and uncluttered API, which can easily be consumed by different front-ends. Not surprisingly, this additional API will be a service layer. In the final installment I’ll be showing you how to implement it in a few easy steps. Don’t miss the last part!
blog comments powered by Disqus |
|
|
|
|
|
|
|