Norgul
Norgul

Reputation: 4783

Laravel DI with interfaces

I have made a repository pattern app, having a repo and interface:

class UserRepository extends EloquentRepository implements UserRepositoryInterface
{
    public function __construct()
    {
        $this->model = new User();
    }
    ...
}

The repository and interfaces as well as extended class and its interface is registered in service provider and is called on app boot.

The questions I have are:

Upvotes: 1

Views: 2221

Answers (2)

Martin
Martin

Reputation: 306

try to make the repositories abstract in the controllers and inject these through constructor.

like this here:


public function __construct(EloquentRepository $repository)
{
   $this->repository = $repository;
}


And in the AppServiceProvider you can inject repositories you will need.

   public function boot()
    {
        // provides any Repository in SomeController

        $this->app->when(SomeController::class)
            ->needs(EloquentRepository::class)
            ->give(function (Application $app) {
                return $app->make(SomeRepositoryInterface::class)
            });
    }

Upvotes: 0

DevK
DevK

Reputation: 9942

Is there a need to watch out for the order of registering? For example, should EloquentRepository class be loaded before the repo, or does Laravel handle that on its own?

I don't quite understand where you would load EloquentRepository as (from the code posted) it seems you're only extending it. Which shouldn't be a problem.

In case I inject UserRepositoryInterface in a controller, is the constructor method called automatically even though I didn't really new-up a class?

Yes. Most of Laravel's main classes (controllers included) are loaded with DI in mind and the dependencies will be resolved automatically.

That being said, since you are injecting an interface and an interface by default cannot be initialized as a class, since it has no implementation - you need to bind an implementation to the interface first in order to use it.

How long does the DI injection "live"? If I inject it in a page controller which calls some other controller and needs the same dependency, does the constructor call twice then, and operate separately in each controller?

My understanding is that a new instance of the class will be created when the next controller is initialized. Unless you bind a class as a singleton.

Is there a difference if I call it like App::make() instead of DI?

App::make(some::class) will automatically resolve the dependencies of class some.

For example:

namespace App;

use App\Dependancy;

class Test 
{
    protected $d;

    public function __construct(Dependancy $d) 
    {
        $this->d = $d;
    }
}

If you call this in the controller: $a = new \App\Test() you will get an error that \App\Test constructor expects class Dependency as first parameter.

But if you initialize it like this: $a = \App::make(\App\Test::class) the Dependency will be automatically resolved.

Upvotes: 3

Related Questions