The key here is to look at which classes should have which responsibilities, and specifically, which responsibilities are needed to make your domain function.

User Domain Object

Should be responsible for telling you about its state with respect to the useful business rules of your application ( isAdmin() , isBanned() , isSuspended() , getWarnLevel() ). Think of this object like an API bucket. What do you want to know about it? What useful information can it tell? Build an API that answers those questions. Be careful not to let the User tell you too much about OTHER objects in the system. That should not be its responsibility.

Cares about:

Telling you about itself

Managing its own state

Doesn't care about

Whether it gets persisted

How its made

Any other objects (unless it's an aggregate root)

Lots of other stuff

User Repository

A class responsible for allowing you to retrieve and persist fully formed, existing Users . Maybe they persist only in memory during the current request. Maybe they persist in cache. Maybe they persist in MySQL. It doesn't matter. All this thing does is allow you to get users, and persist them. That is its responsibility. It can, but doesn't have to, know about the persistence mechanism. It only needs to know how to use the persistence mechanism.

( findById($id) , findByEmail($email) , findBanned() , findByCriteria($Criteria) - good candidate for the strategy or specification pattern, save($User) , delete($User) ). Again, the key here is to build an API that satisfies the business rules of the domain. Do you have a need to find a user by email address? Then make that an explicit access point in the repository. If you don't have a need, then don't. How do you need to find Users ? Answer that with an API.

Cares about

Giving you access to existing User objects based on any arbitrary criteria

Invoking the persistence mechanism you've supplied it

Doesn't care about

How exactly User objects are persisted

objects are persisted Making User objects

objects Lots of other stuff

User Factory

UserRepositories are for handling existing User objects, but how do you create them in the first place? With factories. These can be simple factories, that just make one type of user. Or they can be abstract factories, that make different types of users. This is up to you and what your systems needs are. Again, think in terms of what API is needed to satisfy the business rules of your domain space: ( make($type, $data) , makeAdmin($data) , makeMember($data) ). PHP 5.6's variadic operator syntax will make this WAY cleaner to work with btw.

Cares about

Making shiny new Users

Doesn't care about

The source of the data for making those shiny new Users

What you do with the User after it's made

after it's made Lots of other stuff

User Gateway/Mapper

This could be your actual persistence mechanism: it might interface directly with a relational database, make use of a Factory, and get used by the Repository. It does the actual DB fetching, and maps the data into a format that the Factory can digest. The factory shouldn't be responsible for this mapping because it shouldn't have any knowledge of the source format, only the format it needs to assemble the domain object. Thus the mapping responsibility lies with the Gateway/Mapper.

Cares about

Where the User is getting persisted to/retrieved from, and how

is getting persisted to/retrieved from, and how Translating that data from persistence to something a Factory wants

Probably cares about a Factory

Doesn't care about

The specific storage driver (e.g. MySQL, Postgres) - this is where PDO comes in

Making a new User object

object Lots of other stuff

Now, admittedly this looks way more simple than it really is. How do you handle children of aggregates (e.g. the many Comments that belong to one Post )? At what stage do you give those to the Post ? Do you even give them to it all the time, or only when you explicitly ask for it (e.g. via a callback?) These are tough questions that I don't have the answers to, and that are partially answered by your domain needs in the first place.

ORM is a tough problem to solve. Doctrine and Eloquent are excellent, but don't strictly follow the pattern above. That's ok though. The pattern above is a guideline, not a rule. It's goal is to focus on separation of concerns and focused responsibility. It may not be necessary for your application to have all of these layers.

Concerning validation, there are two kinds of validation:

Form input validation Domain object validation

Form validation is usually best done by a form validator class and some rules specifically defined for a given form. Usually you can define those rules in whatever form builder class you have (e.g. Form::text('first_name', array('rules' => 'required|alpha')) ). The controller should take the form validator as a dependency, but should not do the actual validation itself.

Domain object assembly validation (e.g. protecting the integrity of your model) can live either in the domain object itself via setters, or it can live in the factory. This depends entirely on how you plan to construct domain objects.

It should be noted that you should have BOTH types of validation: form validation to validate input, and domain object validation to validate data integrity when you create the object.