The repository pattern is an essential architectural pattern in Laravel applications that promotes clean and maintainable code. By implementing this pattern, you can separate the data access logic from the business logic, leading to improved testability and flexibility. In this tutorial, we will walk you through a complete example of using the repository pattern in a Laravel application, including the controller and views.
Assuming you have the Laravel application installed and database configuration is already done. Let’s continue further from that. If you haven’t any application then create a new one.
Creating the Repository Interface
To begin, let’s create a repository interface that defines the contract for our user repository. In the app/Repositories directory, create a new file called UserRepositoryInterface.php with the following code:
<?php
namespace App\Repositories;
interface UserRepositoryInterface
{
public function getById($id);
public function getAll();
public function create(array $data);
public function update($id, array $data);
public function delete($id);
}
Implementing the Repository
Next, let’s create an implementation of the repository using Laravel’s Eloquent ORM. In the app/Repositories
directory, create a new file called EloquentUserRepository.php with the following code:
<?php
namespace App\Repositories;
use App\Models\User;
class EloquentUserRepository implements UserRepositoryInterface
{
public function getById($id)
{
return User::findOrFail($id);
}
public function getAll()
{
return User::all();
}
public function create(array $data)
{
return User::create($data);
}
public function update($id, array $data)
{
$user = User::findOrFail($id);
$user->update($data);
return $user;
}
public function delete($id)
{
$user = User::findOrFail($id);
$user->delete();
}
}
Binding the Repository Interface
To make the repository accessible throughout the application, open the AppServiceProvider.php file located in the app/Providers directory. In the register() method, add the following code:
$this->app->bind(
\App\Repositories\UserRepositoryInterface::class,
\App\Repositories\EloquentUserRepository::class
);
Creating the Controller
Let’s create a controller that will utilize the user repository to perform CRUD operations. Open the terminal and enter the below command into it:
php artisan make:controller UserController
It will create a new controller called UserController.php. Let’s modify it as per our example:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Repositories\UserRepositoryInterface;
use Illuminate\Http\Request;
class UserController extends Controller
{
private $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
public function index()
{
$users = $this->userRepository->getAll();
return view('users.index', compact('users'));
}
public function create()
{
return view('users.create');
}
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:6',
]);
$this->userRepository->create($data);
return redirect()->route('users.index')
->with('success', 'User created successfully.');
}
public function edit($id)
{
$user = $this->userRepository->getById($id);
return view('users.edit', compact('user'));
}
public function update(Request $request, $id)
{
$data = $request->validate([
'name' => 'required',
'email' => 'required|email',
'password' => 'required|min:6',
]);
$this->userRepository->update($id, $data);
return redirect()->route('users.index')
->with('success', 'User updated successfully.');
}
public function destroy(User $user)
{
$this->userRepository->delete($user->id);
return redirect()->route('users.index')
->with('success', 'User deleted successfully.');
}
}
n the above example, we have defined all necessary methods for performing CRUD operations. The __construct method will initialize a new object for our user repository.
Further, it will manage all operations related to user experiences like showing the view, and success-failure messages.
Creating the Views
Let’s create the views for the user management functionality. In the resources/views/users directory, create the following files:
The index.blade.php (listing all users):
@extends('layouts.app')
@section('content')
<h1>Users</h1>
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-primary">Edit</a>
<form action="{{ route('users.destroy', $user->id) }}" method="POST" style="display: inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger" onclick="return confirm('Are you sure?')">Delete</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
<a href="{{ route('users.create') }}" class="btn btn-success">Add User</a>
@endsection
The create.blade.php (form for creating a new user):
@extends('layouts.app')
@section('content')
<h1>Add User</h1>
<form action="{{ route('users.store') }}" method="POST">
@csrf
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" class="form-control" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Add User</button>
</form>
@endsection
The edit.blade.php (form for editing an existing user):
@extends('layouts.app')
@section('content')
<h1>Edit User</h1>
<form action="{{ route('users.update', $user->id) }}" method="POST">
@csrf
@method('PUT')
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" class="form-control" value="{{ $user->name }}" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" name="email" class="form-control" value="{{ $user->email }}" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Update User</button>
</form>
@endsection
Conclusion
In the above example, we have seen the implementation of a repository design pattern in the Laravel application. Here, we have performed the CRUD operation of a user using a repository design pattern.
By adopting the repository pattern, you can achieve cleaner code architecture, improved testability, and better code maintenance in your Laravel applications.