ineedhelp
ineedhelp

Reputation: 227

PHP Repository Pattern Implementation Questions

What should Repositories return from service calls?

An Entity (or Collection of Entities), or instead a reference to itself, which could then be used to access an property that holds a collection of Entities, for example?

Take this sample code:

$user = $userRepository->findById(1);

or

$users = $userRepository->findAll();

I think in most code, a User Entity object, or Users Collection Entity would be returned from a call like this.

It seems a bit strange to me that from one direction, a Repository will return objects directly, yet from the other end, it will hold them in state before acting upon them. Take this sample code as an example:

$user = $factory->make('user');
$user->setName($array_data['name']);

$repo->add($user);
$repo->save();

Is this just how it's done?

I think I am expecting to see something a bit more like this, in terms of retrieval:

$users = $userRepository->findAll(); // Returns $userRepository reference

foreach($users->collection() as $user) {
    // Do some operations, or whatever
}

$users->save();

or perhaps, for read only needs:

$users = $userRepository->findAll();
$users = $users->collection(); // Returns User Entities held in state

Clarification as to why it's done one way or another would be much appreciated.

Where does the Factory belong inside the Domain?

Should it be injected as a dependency of the Mapper object? It seems like there must also be Factory access from the controlling code/service layer as well, for creating Entities to submit to the Repository.

That leads into my next question...

What is the preferred way to create new Entities from the controlling class/service layer?

I have seen Factory objects being used, like this:

$user = $factory->make('user');
$user->setName($array_data['name']);

$repo->add($user);

As well as built-in Repository methods, like this:

$repo->saveFromArray($array_data);

In the second example, the $array_data would be forwarded through the repository, to the Mapper, which will then perform the save. Of course the data source would be checked for overlapping records beforehand, in either example.

I assume the first method is preferred? It seems to be a more object-oriented approach.

Upvotes: 4

Views: 1726

Answers (1)

MikeSW
MikeSW

Reputation: 16348

You have many questions...

What should Repositories return from service calls?

Always aggregate roots (AR). AR design is very important, but it's none of the repository's concern. The repository methods return one or many objects as needed by the Domain. There is no Users Collection Enitity, there's a list of Users (which in php probably is an array), don't complicate things.

The Domain repositories should be used only for Domain needs (read or write). The whole object is returned, the repository doesn't return pieces of an AR, but the whole AR. Once again I mention that AR design is very important.

Where does the Factory belong inside the Domain?

Where it's needed. I don't use a factory, at most I have a factory method, but even that is for restoring purposes (if I'm using a memento). You don't have to use a factory to create the domain objects.

What is the preferred way to create new Entities from the controlling class/service layer?

The simplest way possible. For probably 99% of cases, you'll be using the "new" operator. Use Factories only if it gives you a concrete benefit for specific entities.

The Mapper never performs saves, because it's a mapper. Only repositories do persistence work. Mappers 'convert'/copy data from one model to another. You can use mappers to map a domain objects to some data model to be persisted and back.

Upvotes: 1

Related Questions