Laravel Repository Pattern

Jacob Mitchell
3 min readApr 6, 2023
Laravel Repository Pattern

Laravel is a powerful PHP framework that provides a lot of features to help you develop complex applications in a simpler and more efficient way. One of the most important design patterns that Laravel supports is the Repository pattern, which allows you to abstract the data access logic from the application’s business logic. In this article, we will discuss how to implement the Repository pattern in Laravel.

Laravel is a popular PHP framework that provides built-in support for the Repository Pattern. The framework provides several features that make it easy to implement the pattern, such as the Eloquent ORM, the Query Builder, and the Dependency Injection container.

Define the Product Model

The first step in implementing the repository pattern is to define the Product model. A model represents a database table and is responsible for interacting with that table. In Laravel, you can define a model by extending the Illuminate\Database\Eloquent\Model class. Here's an example of a Product model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
protected $fillable = [
'name',
'description',
'price',
];
}

In this example, the Product model has three fields: name, description, and price. These fields are defined in the $fillable array, which allows Laravel to mass-assign them when creating or updating a product.

Define the Product Repository Interface

The next step is to define the ProductRepository interface. This interface defines the methods that the repository will implement. Here’s an example of a ProductRepository interface:

namespace App\Repositories;

interface ProductRepository
{
public function all();

public function find($id);

public function create(array $data);

public function update(array $data, $id);

public function delete($id);
}

In this example, the ProductRepository interface has five methods: all(), find($id), create(array $data), update(array $data, $id), and delete($id). These methods represent the basic CRUD operations that a repository should support.

Define the Product Repository Class

The next step is to define the ProductRepository class. This class implements the ProductRepository interface and contains the actual implementation of the methods. Here’s an example of a ProductRepository class:

namespace App\Repositories;

use App\Models\Product;

class ProductRepositoryEloquent implements ProductRepository
{
public function all()
{
return Product::all();
}

public function find($id)
{
return Product::findOrFail($id);
}

public function create(array $data)
{
return Product::create($data);
}

public function update(array $data, $id)
{
$product = Product::findOrFail($id);

$product->update($data);

return $product;
}

public function delete($id)
{
$product = Product::findOrFail($id);

$product->delete();
}
}

In this example, the ProductRepositoryEloquent class implements the ProductRepository interface and provides the actual implementation of the methods. The all() method returns all products, the find($id) method returns a single product by ID, the create(array $data) method creates a new product, the update(array $data, $id) method updates an existing product, and the delete($id) method deletes a product by ID.

Define the Product Repository Service Provider

The final step is to define the ProductRepository service provider. This service provider binds the ProductRepository interface to the ProductRepositoryEloquent implementation. Here’s an example of a ProductRepository service provider:

namespace App\Providers;

use App\Repositories\ProductRepository;
use App\Repositories\ProductRepositoryEloquent;
use Illuminate\Support\ServiceProvider;

class ProductRepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(ProductRepository::class, ProductRepositoryEloquent::class);
}
}

the ProductRepositoryServiceProvider class extends the Illuminate\Support\ServiceProvider class and overrides the register() method. In the register() method, we use the $this->app->bind() method to bind the ProductRepository interface to the ProductRepositoryEloquent implementation.

Using the Product Repository

Now that we have defined the Product model, the ProductRepository interface, the ProductRepositoryEloquent class, and the ProductRepository service provider, we can use the ProductRepository in our code. Here’s an example of how to use the ProductRepository to retrieve all products:

use App\Repositories\ProductRepository;

class ProductController extends Controller
{
protected $products;

public function __construct(ProductRepository $products)
{
$this->products = $products;
}

public function index()
{
$products = $this->products->all();

return view('products.index', compact('products'));
}
}

In this example, we inject the ProductRepository into the ProductController’s constructor using Laravel’s dependency injection. We can then use the $this->products property to call the all() method and retrieve all products.

Conclusion

The repository pattern is a powerful tool that can help you write cleaner, more maintainable code. By separating the data access logic from the rest of the application code, you can make your code more modular, testable, and easier to maintain. In this article, we explored how to implement the repository pattern in Laravel using examples of product classes.

--

--

Jacob Mitchell

Software engineer, Technical writer, writing about software development </>