What is the Repository Pattern in Laravel
Explore the Repository Pattern in Laravel - a design pattern that abstracts the data layer, making your code more testable, flexible, and maintainable.
What is the Repository Pattern in Laravel
The Repository Pattern in Laravel is a design pattern used to abstract the data layer, allowing you to decouple your application from the persistence layer (e.g., Eloquent ORM, Query Builder, or an external API). It acts as a mediator between your controllers and your models, making your code more testable, flexible, and maintainable.
Why Use the Repository Pattern?
- Swappable data sources – Easily switch from Eloquent to an external API or another database layer.
- Better unit testing – Mocks can be injected into the repository interface.
- Cleaner, more organized code
When to Use the Repository Pattern
Repetitive queries across controllers:
Centralizes queries so you write once, reuse everywhere.
Unit testing needed:
Allows easy mocking/stubbing of data access logic.
Switching data sources:
You can change from Eloquent to API/Redis without touching controller code.
Large-scale applications:
Helps organize codebase using SOLID and DDD principles.
When Not to Use It
- Simple CRUD apps
- No testing needs
- Prototype or MVP
Use the repository pattern when you find yourself repeating queries, writing complex logic in controllers, or planning for growth/testing.
Common Use Cases
- E-commerce systems – complex product, cart, and order logic.
- Learning management systems (LMS) – many relationships between students, courses, quizzes, etc.
- APIs – where you want clear separation between the API logic and the DB access.
- Microservices – to isolate data layer behind contracts (interfaces).
EXAMPLE
1. Create an Interface
1
2
3
4
5
6
7
8
9
10
11
12
// app/Repositories/PostRepositoryInterface.php
namespace App\Repositories;
interface PostRepositoryInterface
{
public function all();
public function find($id);
public function create(array $data);
public function update($id, array $data);
public function delete($id);
}
2. Create the Repository Implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// app/Repositories/PostRepository.php
namespace App\Repositories;
use App\Models\Post;
class PostRepository implements PostRepositoryInterface
{
public function all()
{
return Post::all();
}
public function find($id)
{
return Post::findOrFail($id);
}
public function create(array $data)
{
return Post::create($data);
}
public function update($id, array $data)
{
$post = Post::findOrFail($id);
$post->update($data);
return $post;
}
public function delete($id)
{
$post = Post::findOrFail($id);
return $post->delete();
}
}
3. Bind the Interface to the Implementation
In App\Providers\AppServiceProvider
or a custom service provider:
1
2
3
4
5
6
7
use App\Repositories\PostRepository;
use App\Repositories\PostRepositoryInterface;
public function register()
{
$this->app->bind(PostRepositoryInterface::class, PostRepository::class);
}
4. Use It in a Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use App\Repositories\PostRepositoryInterface;
class PostController extends Controller
{
protected $postRepo;
public function __construct(PostRepositoryInterface $postRepo)
{
$this->postRepo = $postRepo;
}
public function index()
{
$posts = $this->postRepo->all();
return view('posts.index', compact('posts'));
}
}
✅ Benefits in Practice
- Helps with unit testing (you can mock
PostRepositoryInterface
). - Makes your code follow SOLID principles (especially the Dependency Inversion Principle).
- Makes it easier to refactor your data source later.