Handling Collections of Aggregate Roots – the Repository Pattern

One of the most typical aspects of traditional Domain-Driven Design (DDD) architectures is the imperative persistence agnosticism exposed by the Domain Model. In more conservative designs, including several implementations based on Active Record or Data Table Gateway (which in pursuit of a rather deceiving simplicity often end up poisoning domain logic with infrastructure), there’s always an explicit notion of an underlying storage mechanism living and breathing down the line, usually a relational database. Domain Models on the other hand are conceptually designed from the beginning in a rigid “storage-unaware” nature, thus shifting any persistence logic out of their boundaries.

Even considering that DDD is somewhat elusive when it comes to making a direct reference to the “database,” in the real world there most likely will be at least one sitting behind the scenes since the Domain Model must ultimately be persisted in one form or another. It’s pretty usual therefore to have a mapping layer deployed somewhere between the Model and the Data Access layer. Not only does this actively push for maintaining a decent level of isolation between each layer, but it shields every complex detail involved in moving domain objects back and forward across the seams of the layers in question from the client code.

Mea culpa aside, it’s fair to admit dealing with the oddities of a layer of Data Mappers is quite a burden, often dropped into a “code once/use forever” strategy. Even though, the above schema performs decently well in fairly simplistic conditions where there are just a few domain classes handled by a small number of mappers. The situation can become a lot more awkward however when the model starts to bloat and increase in complexity, since additional mappers will be surely added over time.

This shows in a nutshell that opening the doors of persistence ignorance when working with rich Domain Models, composed of several complex aggregate roots, can be quite difficult to accomplish in practice, at least without having to create expensive object graphs in multiple places or treading the sinful path of duplicated implementations. Worse, in large systems that need to pull expensive collections of aggregate roots from the database that match different criteria, the whole query process can be on its own an active, prolific promoter of this flawed duplication when not properly centralized through a single entry point.

In such convoluted use cases, the implementation of an additional abstraction layer, commonly known in DDD parlance as a Repository, which mediates between the Data Mappers and the Domain Model, can effectively help to reduce query logic duplication to a minimum while exposing onto the Model the semantics of a real in-memory collection.

Unlike mappers, though, which are part of the infrastructure, a repository characterizes itself as speaking the model’s language, as it’s intimately bound to it. And because of its implicit dependency on the mappers, it preserves the persistence ignorance as well, therefore providing a higher level of data abstraction, much closer to the domain objects.

It’s sad but true the benefits a repository brings to the table can’t be so easily realized for every single application that might exist out there, hence its implementation is only worthwhile if the situation warrants. Anyway, it’d be pretty informative to build a small repository from scratch so that you can see its inner workings and unveiling what’s actually beneath its rather esoteric shell.

Doing some Preliminary Groundwork

The process of implementing a repository can be pretty complex, because it actually hides all the nuts and bolts of injecting and handling the Data Mappers behind a simplified collection-like API, which in turn also inject some kind of persistence adapter, and so on. This successive injection of dependencies, coupled to the hiding of extensive logic, explains why a repository is often considered a plain Façade, even when some opinions currently diverge from that concept.

In either case, the first step that we should take to get a functional repository up and running is create a basic Domain Model. The one that I plan to use here will be charged with the task of modelling generic users, and its bare-bones structure looks like this:

<?php
namespace Model;

interface UserInterface
{
    public function setId($id);
    public function getId();
    
    public function setName($name);
    public function getName();
    
    public function setEmail($email);
    public function getEmail();
    
    public function setRole($role);
    public function getRole();
}
<?php
namespace Model;

class User implements UserInterface
{
    const ADMINISTRATOR_ROLE = "Administrator";
    const GUEST_ROLE         = "Guest";
    
    protected $id;
    protected $name;
    protected $email;
    protected $role;

    public function __construct($name, $email, $role = self::GUEST_ROLE) {
        $this->setName($name);
        $this->setEmail($email);
        $this->setRole($role);
    }
    
    public function setId($id) {
        if ($this->id !== null) {
            throw new BadMethodCallException(
                "The ID for this user has been set already.");
        }
        if (!is_int($id) || $id < 1) {
            throw new InvalidArgumentException(
                "The user ID is invalid.");
        }
        $this->id = $id;
        return $this;
    }
    
    public function getId() {
        return $this->id;
    }
    
    public function setName($name) {
        if (strlen($name) < 2 || strlen($name) > 30) {
            throw new InvalidArgumentException(
                "The user name is invalid.");
        }
        $this->name = htmlspecialchars(trim($name), ENT_QUOTES);
        return $this;
    }

    public function getName() {
        return $this->name;
    }

    public function setEmail($email) {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                "The user email is invalid.");
        }
        $this->email = $email;
        return $this;
    }
    
    public function getEmail() {
        return $this->email;
    }
    
    public function setRole($role) {
        if ($role !== self::ADMINISTRATOR_ROLE
            && $role !== self::GUEST_ROLE) {
            throw new InvalidArgumentException(
                "The user role is invalid.");
        }
        $this->role = $role;
        return $this;
    }
    
    public function getRole() {
        return $this->role;
    }
}

In this case in particular, the Domain Model is a pretty skeletal layer, barely above a plain data holder capable of validating itself, which defines through just a segregated interface and a banal implementer the data and behavior of some fictional users. To keep things uncluttered and easy to understand, I’m going to keep the model that thin.

With the model already going about its business in relaxed isolation, let’s make it a little bit richer by adding to it an additional class, responsible for handling collections of user objects. This “addendum” component is just a classic array wrapper implementing the Countable, ArrayAccess and IteratorAggregate SPL interfaces:

<?php
namespace ModelCollection;
use MapperUserCollectionInterface,
    ModelUserInterface;
    
class UserCollection implements UserCollectionInterface
{
    protected $users = array();
    
    public function add(UserInterface $user) {
        $this->offsetSet($user);
    }
    
    public function remove(UserInterface $user) {
        $this->offsetUnset($user);
    }
    
    public function get($key) {
        return $this->offsetGet($key);
    }
    
    public function exists($key) {
        return $this->offsetExists($key);
    }
    
    public function clear() {
        $this->users = array();
    }
    
    public function toArray() {
        return $this->users;
    }
    
    public function count() {
        return count($this->users);
    }
    
    public function offsetSet($key, $value) {
        if (!$value instanceof UserInterface) {
            throw new InvalidArgumentException(
                "Could not add the user to the collection.");
        }
        if (!isset($key)) {
            $this->users[] = $value;
        }
        else {
            $this->users[$key] = $value;
        }
    }
    
    public function offsetUnset($key) {
        if ($key instanceof UserInterface) {
            $this->users = array_filter($this->users,
                function ($v) use ($key) {
                    return $v !== $key;
                });
        }
        else if (isset($this->users[$key])) {
            unset($this->users[$key]);
        }
    }
    
    public function offsetGet($key) {
        if (isset($this->users[$key])) {
            return $this->users[$key];
        }
    }
    
    public function offsetExists($key) {
        return ($key instanceof UserInterface)
            ? array_search($key, $this->users)
            : isset($this->users[$key]);
    }
    
    public function getIterator() {
        return new ArrayIterator($this->users);
    }
}

In fact, placing this array collection within the model’s boundaries is entirely optional, as pretty much the same results can be yielded by using a plain array. In this case however, by relying on a standalone collection class makes easier to access sets of user objects fetched from the database through an object-oriented API.

In addition, considering that the Domain Model must be entirely ignorant about the underlying storage set down in the infrastructure, the next logical step that we should take is implement a mapping layer that keeps it nicely separated from the database. Here are the elements that compose this tier:

<?php
namespace Mapper;
use ModelUserInterface;

interface UserCollectionInterface extends Countable, ArrayAccess, IteratorAggregate 
{
    public function add(UserInterface $user);
    public function remove(UserInterface $user);
    public function get($key);
    public function exists($key);
    public function clear();
    public function toArray();
}
<?php
namespace Mapper;
use ModelRepositoryUserMapperInterface,  
    ModelUser;

class UserMapper implements UserMapperInterface
{    
    protected $entityTable = "users";
    protected $collection;

    public function __construct(DatabaseAdapterInterface $adapter, UserCollectionInterface $collection) {
        $this->adapter = $adapter;
        $this->collection = $collection;
    }
    
    public function fetchById($id) {
        $this->adapter->select($this->entityTable,
            array("id" => $id));
        if (!$row = $this->adapter->fetch()) {
            return null;
        }
        return $this->createUser($row);
    }
    
    public function fetchAll(array $conditions = array()) {
        $this->adapter->select($this->entityTable, $conditions);
        $rows = $this->adapter->fetchAll();
        return $this->createUserCollection($rows);
        
    }
    
    protected function createUser(array $row) {
        $user = new User($row["name"], $row["email"],
            $row["role"]);
        $user->setId($row["id"]);
        return $user;
    }
    
    protected function createUserCollection(array $rows) {
        $this->collection->clear();
        if ($rows) {
            foreach ($rows as $row) {
                $this->collection[] = $this->createUser($row);
            }
        }
        return $this->collection;
    }
}

Out of the box, the batch of tasks performed by UserMapper are fairly straightforward, limited to just exposing a couple of generic finders which are charged with pulling in users from the database and reconstructing the corresponding entities through the createUser() method. Moreover, if you’ve already sunk your teeth into a few mappers before, or even written your own mapping masterpieces, surely the above should be pretty easy to understand. Quite possibly the only subtle detail worth stressing is that the UserCollectionInterface has been placed into the mapping layer, rather than in the model’s. I decided to do so pretty much deliberately in this case, as that way the abstraction (the protocol) that the user collection depends on is explicitly declared and owned by the higher-level UserMapper, in consonance with the guidelines promoted by the Dependency Inversion Principle.

With the mapper already set, we could just consume it right out of the box and pull in a few user objects from storage to get the model hydrated in a snap. While at first glance this would seem to be the right path to pick up indeed, in fact we’d be unnecessarily polluting application logic with infrastructure, as the mapper is effectively a part of it. What if down the road it becomes necessary to query user entities according to more distilled, domain-specific conditions, other than just the blanket ones exposed by the mapper’s finders?

In such cases, there would be a real need to place an additional layer on top of the mapping one, which not only would provide a higher level of data access, but it would carry chunks of query logic through one single point. This is, in the last instance, the wealth of benefits we’d expect to get from a repository.

Implementing a User Repository

In production, repositories can implement under their surface pretty much every thing one can think of in order to expose onto the model the illusion of an in-memory collection of aggregate roots. Nevertheless, in this case we just can’t be so naive and expect to enjoy of such expensive luxuries for free, since the repository that we’ll be building will be a pretty contrived structure, responsible for fetching users from the database:

<?php
namespace ModelRepository;

interface UserMapperInterface
{
    public function fetchById($id);
    public function fetchAll(array $conditions = array());
}
<?php
namespace ModelRepository;

interface UserRepositoryInterface
{
    public function fetchById($id);
    public function fetchByName($name);
    public function fetchbyEmail($email);
    public function fetchByRole($role);
}
<?php
namespace ModelRepository;

class UserRepository implements UserRepositoryInterface
{
    protected $userMapper;
    
    public function __construct(UserMapperInterface $userMapper) {
        $this->userMapper = $userMapper;
    }
    
    public function fetchById($id) {
        return $this->userMapper->fetchById($id);
    }
    
    public function fetchByName($name) {
        return $this->fetch(array("name" => $name));
    }
    
    public function fetchByEmail($email) {
        return $this->fetch(array("email" => $email));
    }
    
    public function fetchByRole($role) {
        return $this->fetch(array("role" => $role));
    }
    
    protected function fetch(array $conditions) {
        return $this->userMapper->fetchAll($conditions);
    }
}

Although sitting on top of a somewhat lightweight structure, the implementation of UserRepository is pretty intuitive considering that its API allows it to pull in collections of user objects from storage that conform to refined predicates which are closely related to the model’s language. Furthermore, in its current state, the repository exposes just some simplistic finders to client code, which in turn exploit the functionality of the data mapper to gain access to the storage.

In a more realistic environment, a repository should have the capability of persisting aggregate roots as well. If you’re in the mood to pitch an insert() method or something else along that line to UserRepository, feel free to do so.

In either case, one effective manner to catch the actual advantages of using a repository is by example.

<?php
use LibraryLoaderAutoloader,
    LibraryDatabasePdoAdapter,
    MapperUserMapper,
    ModelCollectionUserCollection,
    ModelRepositoryUserRepository;

require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$adapter = new PdoAdapter("mysql:dbname=users", "myfancyusername", "mysecretpassword");
$userRepository = new UserRepository(new UserMapper($adapter, 
    new UserCollection()));

$users = $userRepository->fetchByName("Rachel");
foreach ($users as $user) {
    echo $user->getName() . " " . $user->getEmail() . "<br>";
}

$users = $userRepository->fetchByEmail("username@domain.com");
foreach ($users as $user) {
    echo $user->getName() . " " . $user->getEmail() . "<br>";
}

$administrators = $userRepository->fetchByRole("administrator");
foreach ($administrators as $administrator) {
    echo $administrator->getName() . " " . 
        $administrator->getEmail() . "<br>";
}

$guests = $userRepository->fetchByRole("guest");
foreach ($guests as $guest) {
    echo $guest->getName() . " " . $guest->getEmail() . "<br>";
}

As noted previously, the repository effectively interchanges business terminology with client code (the so-called Ubiquitous Language coined by Eric Evans in his book Domain Driven Design), rather than a lower-level, technical one. Unlike the ambiguity present in the data mapper’s finders, the repository’s methods on the other hand describe themselves in terms of “name,” “email,” and “role,” which are certainly a part of the attributes that model user entities.

This distilled higher level of data abstraction, along with the set of full-fledged capabilities required when it comes to encapsulating query logic in complex systems, are certainly among the most compelling reasons which make using repositories appealing in multi-tiered design. Of course, most of the times there’s an implicit trade-off between getting those benefits up front and going through the hassle of deploying an additional abstraction layer, which in more modest applications may be bloated overkill.

Closing Thoughts

Being one of the central concepts of Domain Driven Design, repositories can be found in applications written in several other languages, like Java and C#, just to name a few. In PHP however, they’re still relatively unknown, just making their first shy steps in the world. Despite this, there are some well-trusted frameworks, such as FLOW3 and of course Doctrine 2.x, which will help you embrace the DDD paradigm.

As with any development methodology out there, you don’t have to use repositories in your applications or even smash them unnecessarily with the pile of concepts sitting behind DDD. Just use common sense and pick them up only when you think they’re going to fit your needs. It’s really just that simple.

Image via Chance Agrella / Freerangestock.com

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://aaronsaray.com Aaron Saray

    Great article! I see so many vague examples of what DDD is without the real legitimate PHP code behind it. I hope you’re submitting this on DZone and the like – this is something all ‘advanced’ OO PHP programmers should read. :)

    • Alex Gervasio

      Thanks Aaron for the comments, and of course I’m glad you enjoyed the post. Hopefully, it’ll be helpful for PHP developers wanting to step on the DDD soil as well.

      • http://trace.nl Chris

        Alex thanks for the amazing articles you write!!! Clear and concise and it sparked me to redo the data models I’m using for my facebook framework.

        many many thanks!!!

        • Alex Gervasio

          Hi Chris,
          Nice to know the post has been overall instructive. In general, there’s nothing inherently “evil” with consuming database models, except that they mix up infrastructure (read persistence access) with domain logic. DDD, on the flip side, provides a solid approach for constructing persistence-agnostic domain models, hence focusing exclusively on the web of interactions that exist between domain classes. Bear in mind that the implementation of additional abstract layers, including repositories isn’t mandatory at all. Most of the times, a “simple” mapping layer is all you’ll need to keep up a nice level of isolation between the model and the DAL.

  • http://www.mostofreddy.com.ar mostofreddy

    Muy buen articulo y ejemplos!

  • Alex Gervasio

    Gracias. Un abrazo grande :)

  • Guilherme Fraco

    I’m so glad to see that we have PHP developers concerned about great quality code, well defined responsibilities between parts of a system, and their actual context. DDD is well known in languages such as Java, and I still don’t understand why PHP developers have such a “lazy” posture on study this subjects. TDD, DDD and topics such as Continuous Integration (just to name a few) are, in my opinion, indispensible methodologies to built great and competitive softwares in any languages, and YES, this includes PHP. Alex, you’re doing a great job in “spreading” this type of knowledge to PHP developers around the world. Here in Brazil we appreciate your atention in write great and TOP LEVEL articles. Thanks !

    • Alex Gervasio

      Thanks Guilherme for the kind comments. Nice to know the article has been overall informative, especially when it comes to shedding some light on the foundations of DDD.

  • Chris

    What is the benefit of having these methods in the repository as to having them in the mapper? Now i usually just place these convienence methods in the mapper.

    • Alex Gervasio

      Hey Chris,
      Good question. Keep in mind that the primary role of a repository is behave like a layer much closer to the domain model’s boundaries, capable of pulling in aggregate roots from the persistence. In the article’s snippets, user objects aren’t aggregate roots at all; they’re just POPOs with a few attributes and a rather banal behavior, so fetching them directly through the mappers could be actually more practical, as there’s no need to drop an additional abstraction layer.
      In realistic use cases, though, you’ll want to fetch actual aggregate roots from the database, such as a blog entry along with the associate comments and authors. Placing all this query logic in the mappers works fine for relatively simple applications. In more complex environments, most likely you’ll delegate this task to a repository. What’s more, nothing should stop you from using the repository at the last line of defense for placing model validation as well, but that’s a pretty slippery terrain. The data mappers are infrastructure, while the repositories are part of the model. The difference is subtle yet important.
      Thanks for the feedback.

      • Galen

        I was wondering this also. Alex’s comment cleared this up. Been googling PHP DDD all day, and this is the first result that made sense. Thanks for this.

  • http://jeungun.wordpress.com Jose

    Great article! One question though, are repositories only used for retrieving? How come I don’t see any “RUD” in the repository interface?

    • Alex Gervasio

      Hi Jose,
      In a “purist” implementation, the only and sole purpose of a repository is to pull in aggregate roots from the database. Nothing more, nothing less. That’s why the repository’s interface declares just a few distilled finders, while any “writing” method is out of the picture. Keep in mind that aggregate roots can be eventually complex and bloated object graphs, so the repository neatly hides from the model all the query logic required for fetching batches of graphs that match a given predicate, either by using in turn the data mappers or something along that line, usually closer to the database.
      For obvious (and pragmatic) reasons, you can take a more relaxed approach and give the repo the ability for saving and even deleting entities.
      As I posted before, I’ve seen occasionally repositories “polluted” with validation logic as well, as a defensive form of preventing entities to be created in an invalid state, which can be pretty handy if the entities are modeled up front as rather passive structures that aren’t capable of validating themselves. To sum up, there’s no a rigid, dogmatic way to implement a repository. If you ever get one, make sure its existence is largely justified. Thanks!

  • http://jeungun.wordpress.com Jose

    I usually use some sort of repository as well eg a Dao where I have an interface for CRUD methods (find, update, create, delete). Inside queries written in PDO. Is this okay? What would I need a database adapter for? What extra value will be given by one more layer of indirection?

    • Alex Gervasio

      The reason for having a database adapter, or in more abstract terms, a persistence adapter is simply decoupling the DAO from your PDO implementation. If you ever need to make the DAO talk to a different persistence mechanism (you know, a web service, a noSQL database, such as CouchDB or MongoDB ) you don’t have to rewrite from scratch your DAO, including its beautifully-crafted CRUD methods In such cases, you simply pass along a different persistence adapter implementer, and you’re done. The fact proves in a nutshell why we should adhere more frequently to the Open/Closed principle and suck the sweet nectar out of Polymorphism :)

      • http://jeungun.wordpress.com Jose

        Can’t I just have multiple dao implementations of a a dao interface? For example UserDaoMysqlImpl, UserDaoMongoDbImpl or UserDaoWebServiceImpl.

        • Alex Gervasio

          Of course you can go for that, Jose. As with many other patterns available out there, you’re just free to pick up the approach you feel will fit your requirements best. The most relevant point to stress here is that either you put the abstraction in the persistence adapter or in the dao, in both cases you’re being nice with the OCP, hence taking advantage of Polymorphism.

  • Vick

    Excellent article.

    • Alex Gervasio

      Thanks Vick. Glad the article has been instructive.

  • Mason

    Spectacular article sir.

    I had a need to explain this kind of setup at a previous job and frankly failed, essentially because I’m just a guy who understands objects at a nuts and bolts level. Often I don’t even know that there’s technical terminology which can be used to exactly identify some of these ideas. All I knew how to do was to build the right moving parts to collect data without making a mess, but now I can point some of my co-workers with their barely-useful ICS degrees here so they can at least understand what I’m trying to accomplish.

    Thanks again, I really appreciate these articles of yours.

    • Alex Gervasio

      Hi Mason,
      Good to hear the post has been of help for understanding a little clearer some of the key concepts that surround the DDD paradigm. Keep up the good work :)

      • http://nerdincan.com Mason

        One thing I could use clarification on was your whole “putting the UserCollectionInterface with the Mapper namespace thing”. Your logic for doing that was that the DataMapper was defining the required functionality of the UserCollection. However, isn’t that traditionally the Repository’s job? In fact, isn’t that the main point of the Repository: assembling collections of model objects and perhaps populating the children of an aggregate root? I guess I’m asking if you have an explicit design reason why the Mapper is responsible for assembling collections instead of the Repository. I’ve always though of the mapper as the thing which “just takes the fields from the PDO request and jams them into models.” Thanks!

        • Alex Gervasio

          Keep in mind that UserCollection is just a generic array wrapper exposing barely state, which could be placed pretty much anywhere you wanted to (i.e. Doctrine simply sits down its collection implementation and interface inside a “Common” folder). Considering the user mapper is, in this case, responsible for populating collections with a few domain objects, I decided to drop the collection interface within the mapper’s namespace, this way defining explicitly the ownership of the collection’s protocol. On the other hand, nobody would disagree with the fact that the role of the repository is certainly to create collections of aggregate roots. But the repository is a sort of bendy façade that hides the complexities of this process and uses one or multiple mappers to accomplish this behinds the scenes, thus providing the model with the notion of an actual in-memory collection, which can be queried according to different predicates. The leg work, however, is done by the mappers, at least in this case in particular. Thanks!

          • http://nerdinacan.com Mason

            Ahh, I see. I think we just have mildly different design concerns. I’ve always used the repository as “the thing that glues everything together” and the mapper as “the thing that hydrates objects from raw DB fields” It’s nice to see how other people approach the problem. Thanks again. Great series!

  • alex.barylski

    Great article. I’ve read most of your posts on here. You have an excellent writing style, keep up the awesome work. :)

    • Alex Gervasio

      Thanks Alex for the positive feedback. Glad the post has been overall informative :)

  • Martin

    Hello, isn’t there a typo error – missing “null” value? Class UserCollection, line 11: $this->offsetSet(null, $user);

    • Alex Gervasio

      Yes Martin, you’re right. For some reason I forgot to add null to the “add()” method in the collection class. Thanks for catching that.

  • Jordan

    Hi Alex,
    Your article is wonderful. I was thinking that even on small projects it would be a good idea to implement this Repository pattern just because even though it might take a little longer to set everything up, it is the best approach design wise to keep your domain layer (stuff that has nothing to do with data retrieval) completely separate from your infrastructure (way that you get and save data to a db or some other source). I just made those two notes in parenthesis in case someone relatively new to these concepts is reading this post, so that it might click for them like it took forever to click for me. :-) So I guess my question is, would you recommend for someone who has already read all of the PHP language reference, but has not yet utilized all this knowledge, to implement the repository pattern in all their projects even starting with the first project? If not, what would you recommend? A simple DAO for each entity object? And if so, is it proper to have an AbstractDAO that has all the standard CRUD functions already implemented and have all of the DAOs extend the Abstract to get all the functionality? Or is it better to use an interface and implement all of the CRUD methods separately for each DAO? Do you possibly know of a link to a tutorial on this, or do you happen to have one that you wrote that you can share the link to? Sorry for so many questions! It’s just really really really good stuff!!!

    • Alex Gervasio

      Hey Jordan,
      Thanks for the kind comments indeed. To make things short, most likely you may want to implement a repository in large, multi-tiered projects, where it’s necessary to have a centralized mechanism that allows you to query the data access layer according to different criteria and fetch domain objects in a pretty straightforward fashion, pretty much as if you were working with an in-memory collection.
      In small projects, the use of a repository is rather overkill. In such cases, just appeal to a simple DAO capable of performing CRUD operations on the domain model and make your life simpler. If you’re interested in digging deeper into the subject, make sure to take a look at a nice tutorial posted by Federico Cargnelutti here
      addition, http://blog.fedecarg.com/2009/03/15/domain-driven-design-the-repository/
      I hope that points you in the right direction. Thanks!

      • Jordan

        Thanks Alex! I will stick to a DAO until I get to the point to where I am working on complex projects. :-) Do you happen to have or know of any great DAO articles that you can recommend?

        • Alex Gervasio

          A few months ago, I wrote a small -yet customizable DAO for another tutorial here at PHPMaster. Perhaps you may want to check it out, extend it and provide it with all the functionality you’re looking for: http://phpmaster.com/integrating-the-data-mappers/ Thanks.

  • http://codecrumbs.at Haensel

    Hi Alex,

    Excellent post on DDD. Definitely one of the best out there but I was wondering how you would implement pagination/sorting. I’ve read some discussions on this topic but there doesn’t seem to be a real guidance on how to do this. It isn’t business logic, so putting it in your entities doesn’t make sense. One could either implement a service doing this (which feels overly complicated) or put the logic into the collection returned by the repositories which would always lazy load just a few entities, not all of them at once. One could then iterate/paginate/sort them. I am really interested in your thoughts