Use the Repository Design pattern in a Laravel application

Connor Leech
Feb 9, 2018 · 4 min read

I previously wrote about how to build a task app with Laravel and Vue.js. Laravel is a PHP framework for building scalable web applications and APIs. Vue.js is a Javascript framework and alternative to jQuery or React.

🌟 Get Started

$ mysql -uroot -p
mysql> create database laravelTaskApp;

If you’re stuck at this point check out other articles I’ve written about installing MySQL and initial Laravel setup. At localhost:8000 you can see an app that asynchronously adds and deletes tasks. That means it does the operations and displays the up to date data without refreshing the webpage.

The task app we built in the previous tutorial.

🏁 The Repository Design Pattern

We’re going to refactor our app to use the Repository Pattern. The first step is to create a file for app/Repositories/Repository.php.

<?php namespace App\Repositories;

use Illuminate\Database\Eloquent\Model;

class Repository implements RepositoryInterface
{
// model property on class instances
protected $model;

// Constructor to bind model to repo
public function __construct(Model $model)
{
$this->model = $model;
}

// Get all instances of model
public function all()
{
return $this->model->all();
}

// create a new record in the database
public function create(array $data)
{
return $this->model->create($data);
}

// update record in the database
public function update(array $data, $id)
{
$record = $this->find($id);
return $record->update($data);
}

// remove record from the database
public function delete($id)
{
return $this->model->destroy($id);
}

// show the record with the given id
public function show($id)
{
return $this->model-findOrFail($id);
}

// Get the associated model
public function getModel()
{
return $this->model;
}

// Set the associated model
public function setModel($model)
{
$this->model = $model;
return $this;
}

// Eager load database relationships
public function with($relations)
{
return $this->model->with($relations);
}
}

This file defines our Repository class. Instances of this class have a model property that we tie to an Eloquent model. Once this is bound in the constructor we can call Eloquent methods like findOrFail, update or all from the class methods.

The implements RepositoryInterface section isn’t strictly necessary but it adds an extra layer of structure to our code. An interface is a contract that defines the methods a class MUST have defined. In our case the interface looks like this:

<?php namespace App\Repositories;

interface RepositoryInterface
{
public function all();

public function create(array $data);

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

public function delete($id);

public function show($id);
}

If we make new Repositories that implement this interface we’ll always know these methods are defined. Interfaces provide structure so we know what our code needs to do.

Back in our TaskController.php file we instantiate a repository and pass in the Task model to it.

<?php

namespace
App\Http\Controllers;

use App\Task;
use App\Repositories\Repository;
use Illuminate\Http\Request;

class TaskController extends Controller
{
// space that we can use the repository from
protected $model;

public function __construct(Task $task)
{
// set the model
$this->model = new Repository($task);
}

public function index()
{
return $this->model->all();
}

public function store(Request $request)
{
$this->validate($request, [
'body' => 'required|max:500'
]);

// create record and pass in only fields that are fillable
return $this->model->create($request->only($this->model->getModel()->fillable));
}

public function show($id)
{
return $this->model->show($id);
}

public function update(Request $request, $id)
{
// update model and only pass in the fillable fields
$this->model->update($request->only($this->model->getModel()->fillable), $id);

return $this->model->find($id);
}

public function destroy($id)
{
return $this->model->delete($id);
}
}

The Laravel service container will automatically resolve our dependencies and inject them into the controller instance (docs).

At this point our application works exactly the same but our code has been refactored to use repositories and we’ve added a couple more API endpoints.

Source code available on Github


🚀 If you’re a candidate on the job market or startup looking to hire in the Bay Area, feel free to create a profile on Employbl 🤝

Employbl

Find a tech or startup job in the Bay Area.

Connor Leech

Written by

Engineer, writer and community organizer. I built Employbl to help candidates get jobs in the Bay Area: https://employbl.com/

Employbl

Employbl

Find a tech or startup job in the Bay Area.

Connor Leech

Written by

Engineer, writer and community organizer. I built Employbl to help candidates get jobs in the Bay Area: https://employbl.com/

Employbl

Employbl

Find a tech or startup job in the Bay Area.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store