Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel repository - why need to call to interface instead of calling directly to repository file?

I've read about repository pattern.So, I created UserRepositoryInterface.php file

namespace App\Interfaces;

use Prettus\Repository\Contracts\RepositoryInterface;

interface UserInterface extends RepositoryInterface
{
    // Code
}

Then I created UserRepository.php:

<?php

namespace App\Repositories;

use Prettus\Repository\Eloquent\BaseRepository;
use App\Interfaces\UserInterface;

class UserRepository extends BaseRepository implements UserInterface
{
    public function model()
    {
        return User::class;
    }
}

Finally, I bind interface to class in RepositoryServiceProvider.php

    public function boot()
    {
        $this->app->bind(UserInteface::class, UserRepository::class);
    }

When inject repository to class, I wonder that should I inject with UserRepository or UserInterface. I've read that UserInterface should be injected, but I don't understand why we not just using UserRepository, it can be faster, isn't it? Someone help?

Thanks.

like image 404
simpsons3 Avatar asked Aug 31 '25 03:08

simpsons3


2 Answers

To be honest, using repositories with Eloquent is just wasting time. With ActiveRecord all logic for storing and receiving data is already implemented within models. You just DON'T need another class and interface to call User::all(). This is just good example of over engineering.

like image 69
PunyFlash Avatar answered Sep 02 '25 18:09

PunyFlash


The whole point of injecting interface instead concrete class is to have it easier for change/extend/maintenance/test.

Now, in your case here, you have injected UserRepositoryInterface in some controller method or constructor let's say. But UserRepository class is still tightly coupled to Eloquent's code (since it's extending Eloquent's class).

Now imagine you are getting users from another provider/source (maybe from 3rd party through API call). That code you can set in separate class \App\Repositories\ApiCallUserRepository (for instance).

You would also set ApiCallUserRepository (newly created class) to implement \App\Interfaces\UserInterface.

When you have all of this, only change you should make is change in provider or in other words you would just need to instruct application which concrete class to use when interface has been injected dependently. Also, this means that same structure of data should be provided from both concrete classes (repository providers) to class that uses repository (i.e. controller's method), or at least receiving data class/code should expect providing structure whether it was Eloquent Collection whether it's some other type of collection.

This way you have nicely set service that gets users for example. And you can easily choose from which provider you want to get users.

It's not all: in time of execution (i.e. when request is made) you can set appropriate concrete class or make additional code regarding by any arbitrary rules. In Laravel's service container check when()->needs()->give() but also I warmly recommend you to go again through full (page) docs.

Also don't limit yourself, but go through other generic and specific articles about DI:

php-di

designpatternsphp

Symfony DependencyInjection Component

laminas-di

Maybe all of this seems like overhead but in reality it is a good starting position for extending application in good, standard, maintainable, and testable way.

like image 32
Tpojka Avatar answered Sep 02 '25 17:09

Tpojka