The Repository pattern helps you organize how your app talks to data storage. It keeps data access code separate from the rest of your app.
Repository pattern in PHP
<?php interface UserRepository { public function findById(int $id); public function save(User $user); } class UserRepositoryImpl implements UserRepository { public function findById(int $id) { // code to get user from database } public function save(User $user) { // code to save user to database } }
The interface defines what methods the repository must have.
The implementation contains the actual code to get or save data.
<?php interface ProductRepository { public function findAll(); public function findByName(string $name); } class ProductRepositoryImpl implements ProductRepository { public function findAll() { // return all products } public function findByName(string $name) { // return product by name } }
<?php interface OrderRepository { public function findByUserId(int $userId); public function save(Order $order); } class OrderRepositoryImpl implements OrderRepository { public function findByUserId(int $userId) { // get orders for a user } public function save(Order $order) { // save order } }
This program shows a simple User repository using an array to store users. It saves users and finds them by ID.
<?php // Simple User class class User { public int $id; public string $name; public function __construct(int $id, string $name) { $this->id = $id; $this->name = $name; } } // Repository interface interface UserRepository { public function findById(int $id): ?User; public function save(User $user): void; } // Implementation using an array as data storage class UserRepositoryImpl implements UserRepository { private array $users = []; public function findById(int $id): ?User { foreach ($this->users as $user) { if ($user->id === $id) { return $user; } } return null; } public function save(User $user): void { // Replace user if exists, else add foreach ($this->users as $index => $existingUser) { if ($existingUser->id === $user->id) { $this->users[$index] = $user; return; } } $this->users[] = $user; } } // Using the repository $repo = new UserRepositoryImpl(); // Save some users $repo->save(new User(1, "Alice")); $repo->save(new User(2, "Bob")); // Find user by id $user = $repo->findById(1); if ($user !== null) { echo "Found user: " . $user->name . "\n"; } else { echo "User not found\n"; } // Try to find a user that does not exist $user = $repo->findById(3); if ($user !== null) { echo "Found user: " . $user->name . "\n"; } else { echo "User not found\n"; }
The Repository pattern helps you change the data source later without changing your app code.
Use interfaces to define repository methods so you can swap implementations easily.
Keep repository methods simple and focused on data access only.
The Repository pattern separates data access from business logic.
It uses interfaces and classes to organize how data is fetched and saved.
This makes your code cleaner, easier to test, and flexible to change.
Practice
Repository pattern in PHP?Solution
Step 1: Understand the role of Repository pattern
The Repository pattern is designed to separate how data is accessed from how the business logic works.Step 2: Identify the correct purpose
Separating data access from business logic makes code cleaner and easier to maintain.Final Answer:
To separate data access logic from business logic -> Option AQuick Check:
Repository pattern = separation of concerns [OK]
- Thinking Repository connects UI directly to database
- Believing all code should be in one class
- Ignoring the use of interfaces
Solution
Step 1: Recall PHP interface syntax
Interfaces use the keywordinterfacefollowed by method declarations with parentheses and types.Step 2: Check each option
interface UserRepository { public function findUser(int $id); } correctly declares an interface with a method having a typed parameter. class UserRepository { public function findUser(int $id); } usesclassinstead ofinterface. interface UserRepository { function findUser; } misses parentheses. UserRepository interface { public function findUser(int $id); } has wrong syntax order.Final Answer:
interface UserRepository { public function findUser(int $id); } -> Option DQuick Check:
Interface syntax = interface UserRepository { public function findUser(int $id); } [OK]
- Using 'class' instead of 'interface'
- Omitting parentheses in method declaration
- Wrong keyword order in interface declaration
interface UserRepository {
public function findUser(int $id);
}
class UserRepo implements UserRepository {
public function findUser(int $id) {
return "User_" . $id;
}
}
$repo = new UserRepo();
echo $repo->findUser(5);Solution
Step 1: Understand interface and class implementation
The classUserRepoimplementsUserRepositoryand defines the methodfindUserthat returns "User_" concatenated with the id.Step 2: Trace the method call
Calling$repo->findUser(5)returns "User_5" which is then printed.Final Answer:
User_5 -> Option BQuick Check:
Method returns 'User_' + id = User_5 [OK]
- Expecting just the number 5 as output
- Confusing class name with output
- Thinking interface causes error if implemented correctly
interface ProductRepository {
public function getProduct(int $id);
}
class ProductRepo implements ProductRepository {
public function getProduct() {
return "Product";
}
}Solution
Step 1: Compare interface and class method signatures
The interface methodgetProductrequires anint $idparameter, but the class method has no parameters.Step 2: Understand PHP interface implementation rules
When implementing an interface, method signatures must match exactly, including parameters.Final Answer:
Method getProduct() missing parameter in class implementation -> Option CQuick Check:
Method signatures must match [OK]
- Ignoring parameter mismatch
- Thinking class name must match interface name
- Assuming return type is mandatory in interface
Solution
Step 1: Understand flexibility in Repository pattern
Using separate interfaces and classes for each data type allows adding new repositories without changing existing ones.Step 2: Evaluate options for maintainability
Create separate interfaces like UserRepository and ProductRepository, then implement them in separate classes supports open/closed principle: open for extension, closed for modification. Other options mix concerns or lack structure.Final Answer:
Create separate interfaces like UserRepository and ProductRepository, then implement them in separate classes -> Option AQuick Check:
Separate interfaces = flexible extension [OK]
- Putting all logic in one big class
- Using global functions instead of classes
- Avoiding interfaces reduces flexibility
Ready to prove it?
Pass the test and this pattern moves unknown
