Creating A Laravel CRUD Application With The Repository Pattern


Laravel is a powerful PHP framework that simplifies web application development. When building a CRUD (Create, Read, Update, Delete) application, using the Repository Pattern can make your code cleaner, more maintainable, and easier to test. In this blog, we'll guide you through setting up a Laravel project with the Repository Pattern for a CRUD operation.
Project Structure
laravel-crud-repository/
βββ app/
β βββ Http/
β β βββ Controllers/
β β β βββ ProductController.php
β βββ Models/
β β βββ Product.php
β βββ Providers/
β β βββ RepositoryServiceProvider.php
β βββ Repositories/
β β βββ Interfaces/
β β β βββ ProductRepositoryInterface.php
β β βββ Eloquent/
β β β βββ ProductRepository.php
βββ database/
β βββ migrations/
β β βββ xxxx_xx_xx_create_products_table.php
βββ routes/
β βββ api.php
βββ .env
βββ composer.json
βββ artisan
Step 1: Install Laravel
If you haven't installed Laravel yet, run the following command to create a new Laravel project:
composer create-project laravel/laravel laravel-crud-repository
cd laravel-crud-repository
composer create-project laravel/laravel laravel-crud-repository
cd laravel-crud-repository
Step 2: Configure Database
Update your .env
file with your database credentials:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crud_repository
DB_USERNAME=root
DB_PASSWORD=
Run migrations to set up the database:
php artisan migrate
Step 3: Create a Model and Migration
Generate a model with migration for a sample entity, like Product:
php artisan make:model Product -m
Modify the migration file in database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php
:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->decimal('price', 8, 2);
$table->timestamps();
});
}
Run the migration:
php artisan migrate
Step 4: Implement the Repository Pattern
1. Create the Interface in Interfaces
Folder
Create a new folder app/Repositories/Interfaces/
and then the ProductRepositoryInterface.php
file:
namespace App\Repositories\Interfaces;
interface ProductRepositoryInterface
{
public function getAll();
public function getById($id);
public function create(array $data);
public function update($id, array $data);
public function delete($id);
}
2. Implement the Repository in the Eloquent
Folder
Create the Eloquent
folder inside Repositories/
and create ProductRepository.php
:
namespace App\Repositories\Eloquent;
use App\Models\Product;
use App\Repositories\Interfaces\ProductRepositoryInterface;
class ProductRepository implements ProductRepositoryInterface
{
public function getAll()
{
return Product::all();
}
public function getById($id)
{
return Product::findOrFail($id);
}
public function create(array $data)
{
return Product::create($data);
}
public function update($id, array $data)
{
$product = Product::findOrFail($id);
$product->update($data);
return $product;
}
public function delete($id)
{
return Product::destroy($id);
}
}
3. Bind the Repository in the Service Provider
Run:
php artisan make:provider RepositoryServiceProvider
Modify app/Providers/RepositoryServiceProvider.php
:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use App\Repositories\Eloquent\ProductRepository;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(ProductRepositoryInterface::class, ProductRepository::class);
}
}
Register the provider in config/app.php
:
App\Providers\RepositoryServiceProvider::class,
Step 5: Create a Controller and Inject the Repository
Modify app/Http/Controllers/ProductController.php
:
namespace App\Http\Controllers;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use Illuminate\Http\Request;
class ProductController extends Controller
{
protected $productRepository;
public function __construct(ProductRepositoryInterface $productRepository)
{
$this->productRepository = $productRepository;
}
public function index()
{
return response()->json($this->productRepository->getAll());
}
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric',
]);
return response()->json($this->productRepository->create($data));
}
public function show($id)
{
return response()->json($this->productRepository->getById($id));
}
public function update(Request $request, $id)
{
$data = $request->validate([
'name' => 'sometimes|string|max:255',
'description' => 'nullable|string',
'price' => 'sometimes|numeric',
]);
return response()->json($this->productRepository->update($id, $data));
}
public function destroy($id)
{
return response()->json(['deleted' => $this->productRepository->delete($id)]);
}
}
Step 6: Define API Routes
Modify routes/api.php
:
use App\Http\Controllers\ProductController;
Route::apiResource('products', ProductController::class);
Step 7: Test the API
Run the Laravel development server:
php artisan serve
Test using Postman or cURL:
Get all products:
curl -X GET http://127.0.0.1:8000/api/products
Create a product:
curl -X POST -H "Content-Type: application/json" \
-d '{"name": "Laptop", "description": "A gaming laptop", "price": 1500}' \
http://127.0.0.1:8000/api/products
Final Thoughts
By organizing repositories into separate Interfaces
and Eloquent
folders, this approach makes your Laravel project more scalable and structured. This Repository Pattern ensures loose coupling, making it easier to switch to a different data source in the future.
Now you have a Laravel project following the Repository Pattern for CRUD operations! π Let me know if you have any questions!
Related Blogs
As Laravel developers, one of the critical lessons we eventually learn is: not everything should happen in real-time. Whether it's sending emails, processing images, syncing third-party data, or running analytics β pushing these resource-heavy or time-consuming tasks to the background is essential for a performant and responsive application.

As your Laravel application grows, keeping your code organized becomes more important than ever. A bloated controller quickly becomes hard to read, test, and maintain. One of the best solutions to this problem is using the Service Pattern β a pattern that helps separate your business logic from your controllers.

If you're building a Laravel application and want blazing-fast search capabilities, Meilisearch is one of the best tools you can integrate. In this post, weβll explore what Meilisearch is, why you should consider it, its use cases, pros and cons, and how to integrate it into a Laravel project using Docker.
