Getting Started with Repository Pattern in Laravel using Inheritance and Dependency Injection
Tags: laravel, php, inheritance, inversioncontrol
Published: 2021-03-28 01:10:09

# Introduction
This article assumes that you have a basic understanding and fundamentals of PHP and the Laravel framework.
Before we get into the topic we first must understand what is Repository pattern:

> The Repository pattern. Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.

Source: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design#:~:text=of%20Work%20patterns.-,The%20Repository%20pattern,from%20the%20domain%20model%20layer.

# Create a fresh Laravel project
Now open up a terminal and install a fresh Laravel project,

```bash
composer create-project laravel/laravel laravel-repository-pattern
```

Then open this in your code editor (VS Code).

I am not going to go through the installation process since this article does not aim to teach about installing a Laravel project. Go to the official docs for reference instead, https://laravel.com/docs/8.x#installation-via-composer

# Creating a base interface and base repository class
Create a directory inside the app and name it as Repository and inside it create another directory Eloquent then create a file named `BaseRepository.php` inside Eloquent directory and create an interface and name it `EloquentRepositoryInterface.php` inside Repository . If you did it correctly you will have the following file structure.

```
- app
  - Repository
    - Eloquent
      - BaseRepository.php
    - EloquentRepositoryInterface.php
```

Then inside the interface EloquentRepositoryInterface.php , write an interface that will contain all the common methods that are used when we are accessing our database to retrieve, store, and remove data. (CRUD)

We also want to set standards when creating our repository interface, because we want the method names to be self-describing and that we should know what we get when we use the method. We can use the following verbs: 'find', 'get', 'remove', 'update' and etc that simply describes what it does.

The interface does not care about the implementation details, we only define the method names, what arguments are being passed into it and what we expect it returns. We can simply do that by type hinting it. This what makes it beautiful because whenever we had to change a Data Provider (I am talking about Eloquent ORM, DB, or any 3rd party APIs if there's any), we only have to create another class specifically for it and we do not need to replace code.

# Defining methods inside the EloquentRepositoryInterface
Now let us define the methods that we will be using throughout our entire application in this interface.
Here is an example,

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kktlg68m2e3r0hwr6925.png) 

As you may have noticed the method names are verbose and contains the verbs we just described. Making method names verbose actually makes everything easier.

# Implementing the EloquentRepositoryInterface inside the BaseRepository class

Inside the `BaseRepository` we created a protected property named as $model and it will receive an instance of class Model. In our constructor we inject the Model class and assign the instance into the $model property so it will be available to all methods. These are the important part of our `BaseRepository` class since any new repositories will be extending to this base repository and they won't have to rewrite what we just wrote regarding the implementation details that we interfaced against the `EloquentRepositoryInterface`.

Here is an example,

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgihckmhr5kxr8xyoskb.png) 

# Binding the interface and the repository class in RepositoryServiceProvider class

To your terminal and execute this command to create the class,

```bash
php artisan make:provider RepositoryServiceProvider
```

Then inside that class, inside `register()` method is here me bind the `EloquentRepositoryInterface.php` and the actual repository, in this case it it the `BaseRepository.php` that we created.
Make sure to import these files into the `RepositoryServiceProvider` class.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsqocemz0ifwjzk7hd5v.png) 

And now to make these changes available in our entire application, we register the `RepositoryServiceProvider` class inside the `AppServiceProvider`

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxjnxj7cgph4q7q8c7zj.png) 

Then execute this composer command in your terminal to read the bindings,

```bash
composer dump-autoload
```

If it doesn't work you must delete the cache manually if you are having problems. These files should be deleted specifically as they will get auto-generated by Laravel whenever we run a caching command. And normally these files are being ignored by git.

```
- app
  - bootstrap
    - cache (Delete these files below)
      - config.php
      - packages.php
      - services.php
```

# Adding a UserRepository

Now that we have a our BaseRepository defined, when we create another module or feature it should give us a boost in development time since we eliminated it by applying abstraction using the Repository Pattern.

Now just create another interface and a repository class.
In your terminal execute these commands to create the files,

```bash
touch app/Repository/UserRepositoryInterface.php
touch app/Repository/Eloquent/UserRepository.php
```

Now inside `UserRepositoryInterface` we only have to define the interface and extend on to the `EloquentRepositoryInterface`

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oj5qh1e4zxfu0hege3b7.png) 

And then inside the `UserRepository` class, we still implement the `UserRepositoryInterface` that we just created and extend `BaseRepository` class, by doing this we are applying Inheritance, we inherit all the methods that we just defined from our `BaseRepository` class and we will be able to access to the fields inside `BaseRepository` class so we do not have to rewrite everything. One thing we only want to override is the first parameter in our constructor, from the base repository it is the Model class, but since it is a user repository then we should replace it with the User model.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huplf6ced8vhe3dq3ii9.png) 

And now inside our user repository also contains the methods that we implemented inside the base repository.

And now bind the UserRepositoryInterface with the UserRepository inside the RepositoryServiceProvider class so our application will recognize this new repository that we created in the entire application.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgnfg25epej6u2ucwo5t.png) 

Then execute the command again,

```bash
composer dump-autoload
```

I typically execute this command every time I add a new repository, if I don't then Laravel does not know or recognize about this new repository that we just created.

# Creating a UserController and applying Dependency Injection to use UserRepository

In your terminal execute this command,

```bash
php artisan make:controller UserController
```

and define a route inside `routes/api.php`,

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v9hlbz4592q874mivdww.png) 

And now inside our `UserController` let us define method index() but before that in our constructor we want to inject the `UserRepository` into the `Contoller` so that we will have all the methods available at our disposal. In this case the index() method in the Controller is commonly known to return a list of resources, so let's make that as is.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sy03wq4avouxcm0myo3q.png) 

The Repository Pattern also allows us to write less code inside our Controllers and that makes it even better rather having a giant code in the Controller which isn't what we want if we are aiming for better maintainability and readability. Let's keep it that way, clean controllers.

In case you don't agree with me because I am only showing a simple example and it's for retrieving all users only, then for creating a new user and sometimes we have to put some logic into it, maybe some if-else statements, that actually is considered a code smell and we don't want to do that. And also what about if you have to use the same logic in a different Controller, without creating a repository you will have to copy and paste these code. So when we are using the Repository Pattern we just inject it to the class that we need it for without having to rewrite logic.

So let us test that the route that we created by accessing this link in your browser `http://localhost:8000/api/users`

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pm2qs33ntzcd1xbcszgs.png) 

We should see an empty set. That means everything we did worked and it makes sense because we haven't created any users yet.

So let us create users using the factory, open to your terminal and go to tinker CLI,

```bash
php artisan tinker
```

Then execute this command to create 10 users

```php
User::factory(10)->create()
```

Then go back to your browser and hit refresh and you should see 10 users being returned from the API.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6nljem0ne2a5l7rql35q.png) 

And there we have it!

# Conclusion
In leveraging on this design pattern we took some time to set it up in exchange for better readability and maintainability of our codebase. By doing abstraction and encapsulation we eliminate code duplications as we created a `BaseRepository` that shares all the common methods in every new repository that uses Eloquent ORM.

So for any small changes that we will make in the future, we don't have to bother updating every single file because we extended the common methods and by apply a single change saves us ample time and reduces cognitive load and that makes us happy.

On the other hand, this will make our code testable and we can easily scale it. But this isn't a silver bullet unfortunately, we might have sacrificed a little bit of performance as having these repositories are at the center between our data provider and our Controllers or any class that we might need to get data from.

If you aren't using Repository Pattern yet, make sure to try it out yourself. Thank you for taking the time to read and I hope this helps you out in getting started with Repository Pattern in Laravel.

Full source code: https://github.com/carlomigueldy/laravel-repository-pattern