Table of Contents
12. Repositories — Where Entities Live
“Now that I have entities… where do they live?”
By now, we’ve met:
- Entities — long‑lived concepts with identity
- Value Objects — small pieces of meaning
- Collections — groups of things that belong together
But there's a question hiding in the background:
“Where do entities come from?
And where do they go when I'm not using them?”
In real applications, entities don't float around in memory forever.
They need a place to live — a place to be stored, retrieved, and found again later.
That place is called a repository.
1. Before Any Code: What Is a Repository?
Let's return to the desk metaphor.
Imagine a filing cabinet labeled:
Users
Inside the cabinet, we keep folders:
- User #1
- User #2
- User #3
Each folder is an entity.
The cabinet is the repository.
The repository knows:
- how to find a user
- how to store a user
- how to return a collection of users
- how to save changes
- how to remove a user
But the important part here is:
The cabinet hides how it stores things.
And that is fine because
we only care that it can store and retrieve.
So whether the cabinet uses:
- a database
- a JSON file
- an API
- a CSV
- or a memory array
…doesn't matter to the rest of our code.
The repository is the interface between our domain and our storage.
Domain — the ideas our application cares about
(users, posts, orders)
Storage — the place where those ideas are kept
(database, files, API)
2. Why Repositories Exist
Repositories solve a simple but important problem:
Our domain code should not know how storage works.
Our code should be independent of it.
Entities represent ideas.
Repositories handle persistence.
Keeping them separate makes our code:
- cleaner
- easier to test
- easier to change
- easier to understand
If we ever switch from MySQL to PostgreSQL,
or from files to a database,
our domain code doesn't change
— only the repository does.
3. A Simple Repository Interface
Here's a gentle example of what a repository might look like:
interface UserRepository { public function find(int $id): ?User; public function save(User $user): void; public function all(): UserCollection; }
Let's slow down:
find()→ “Give me the user with this ID”.save()→ “Store this user”.all()→ “Give me all users as a collection”.
This is the idea of a repository — not the storage details.
4. A Simple In‑Memory Implementation
To make the idea easy to see, we'll start with an in‑memory repository:
class InMemoryUserRepository implements UserRepository { private array $items = []; public function find(int $id): ?User { return $this->items[$id] ?? null; } public function save(User $user): void { $this->items[$user->id] = $user; } public function all(): UserCollection { $collection = new UserCollection(); foreach ($this->items as $user) { $collection->add($user); } return $collection; } }
New to these tokens? see the detailed breakdown here →Code Explained
This is not production code — it' s a teaching tool.
It shows the shape of a repository without involving databases or frameworks.
5. What the Repository Gives Us
Repositories give our application:
- a single place where entities live
- a clear boundary between domain and storage
- a predictable way to retrieve and save entities
- a consistent interface no matter how storage works
- testability — we can swap in a fake repository for tests
Repositories are
the “homes” of our entities.
6. Repositories and Collections
Repositories and collections work together:
- A repository returns a collection of entities.
- A collection holds many entities.
- The domain code doesn't know or care how the repository built the collection.
This keeps our domain code clean and expressive:
$users = $userRepository->all(); foreach ($users->all() as $user) { // work with each user }
The domain reads like a story.
7. When Repositories Are the Right Tool
Use a repository when:
- we need to store entities
- we need to retrieve entities
- we want to hide storage details
- we want a clean domain
- we want testable code
Repositories are the bridge between
our domain and our storage.
8. When Repositories Are Too Much
If we're writing:
- a tiny script
- a throwaway tool
- a one‑off experiment
…we don't need repositories.
Repositories shine in real applications with real data.
9. The Mental Model
A repository is a filing cabinet for our entities.
It:
- stores them
- retrieves them
- returns collections
- hides storage details
- keeps our domain clean
Use repositories when our application needs a stable,
predictable way to manage entities.
10. When to Ask AI for a Repository
The moment when persistence becomes a concept
Conversation Example
We ask:
“Save the User to the database.”
AI writes raw SQL inside our service.
Then we ask:
“Load the User by ID.”
AI writes more SQL.
Then we ask:
“List all users.”
More SQL.
Now we “feel it”:
- persistence logic is leaking everywhere
- our service is doing too much
- the domain is getting noisy
This is the moment to say:
“Move all persistence into a UserRepository.”
AI produces:
$user = $userRepository->find($id); $userRepository->save($user);
Rule of Thumb
If we see SQL or storage logic in our domain
— ask for a Repository.
Summary
Repositories introduce a new kind of boundary in our code — a place where ideas meet storage. If the concept feels abstract at first, that’s normal.
Revisit the metaphors, explore the examples, and let the idea settle. This is the beginning of understanding how real applications are shaped.
Tony de Araujo —New York
