Let’s face it: building a full-featured ORM in PHP (or in any other programming language) is a challenging and difficult process that requires careful planning. You'll need a solid background in some popular data persistence patterns, such as Active Record and Data Mapper. That’s a tall order, especially since this kind of package must be able to handle all of the possible relationships between the objects that compose an application, not to mention the validation that must be performed on them. Fortunately, there’s a healthy variety of ORMs available that will do the hard work for you. What’s more, Doctrine, RedBeanPHP and Propel (just to name a few) are good examples of well-trusted ORMs that provide a remarkable set of features right out of the box. While it’s fair to admit that these libraries (and others) boast many happy users in active and vibrant communities, in some use cases, using them may be overkill. Perhaps there are times when you only need to define some common relationships between your domain objects and use some clever approaches (like proxy objects) to load them on request from the database, and nothing else. If at this moment you’re facing a situation like this, hopefully this tutorial will catch your attention. It will show you in a step-by-step manner how to build a small ORM, which you’ll be able to tweak and customize at will to fit your own requirements. Moreover, if you've already read the two installments that precede this one, it’s probable that you’re familiar with the inner workings of this sample ORM. In those chapters I implemented the ORM’s data access and mapping layers, along with a simple domain model. To be frank, the development of this last tier is entirely optional; however, it's useful for demonstrating the ORM’s actual functionality in the deployment of a blog program, which naturally will handle some “typical” domain objects, namely blog entries, comments and authors. With the aforementioned layers ready to be put into action, it’s time to give to the project its final touches. In line with this idea, in this last episode I’ll be adding to the ORM the remaining components that it needs to work as intended. These include a mixture of proxy classes, dependency injection containers and a few basic services. Want to see how all these pieces can be put to work side by side in a productive way? Then keep reading! Creating Proxy Classes In consonance with the concepts deployed in the introduction, it’s necessary to add to the ORM’s existing structure a set of proxy classes. These will be responsible for lazy-loading domain objects from the underlying storage (in this particular case a MySQL database). With that said, here’s the definition of these proxies, along with the interface that they implement. Check them out: (Blog/Model/Proxy/ProxyInterface.php) <?php namespace Blog\Model\Proxy; interface ProxyInterface
(Blog/Model/Proxy/AbstractProxy.php) <?php namespace Blog\Model\Proxy; abstract class AbstractProxy /** /** /**
(Blog/Model/Proxy/EntityProxy.php) <?php namespace Blog\Model\Proxy; class EntityProxy extends AbstractProxy implements ProxyInterface /**
(Blog/Model/Proxy/CollectionProxy.php) <?php namespace Blog\Model\Proxy; class CollectionProxy extends AbstractProxy implements ProxyInterface, \Countable, \IteratorAggregate /** /** /** From the above code snippet, it’s clear to see how the aforementioned proxy classes do their thing. Simply put, they act like “stand-in” elements, which use the functionality of an injected mapper (notice the implementation of the constructor in the abstract proxy) to fetch on request from the database either a single entity or a collection of them. Although the use of proxies might seem somewhat confusing and even irrelevant at this point, don't worry. When I show you how to retrieve from storage some blog entries and lazy-load the related comments and authors, you’ll realize how useful they are in the implementation of more efficient model persistence strategies. So far, so good. Having shown you the previous proxy classes, this sample ORM is now a bit more functional. However, there’s no need to rush, as there are still some additional components that must be constructed to improve the project’s overall efficiency. Object instantiation should be separated as much as possible from application logic. To achieve this goal, in the next section I’ll be defining a couple of dependency injection containers, which will neatly hide from client code the creation of some complex object graphs. To see how this will be done, click on the link below and read the lines to come.
blog comments powered by Disqus |
|
|
|
|
|
|
|