Search code examples
phplaraveldependency-injectioncoupling

Laravel DI coupling differences


What is the difference in class coupling if you use these 3 types of usages:

Case 1

use UserRepository

...

UserRepository::getUser();

Case 2

App::make('UserRepository')->getUser();

Case 3

public function __construct(UserRepository $userRepository)
{
    $this->userRepository = $userRepository;
}
...
$this->userRepository->getUser();

Is there any reason to prefer one over the other?

EDIT

I feel as though the constructor option is the best way to go, but I find myself in question when I need to include 3 services and 3 repositories in the controller which then very soon escalates to 6 parameters in constructor.

EDIT - Case 4

What about when you're using a facade instead?

EDIT - Case 5

What about when you specify it as \UserRepository?


Solution

  • First of all, the idea of the Repository is to have an Interface (UserRepositoryInterface) and classes that implement it (MySQLUserRepository, RedisUserRepository). It gives you a quick way to change the storage of users through your DI container by calling an interface:

    public function __construct(UserRepositoryInterface $userRepository)
    {
        $this->userRepository = $userRepository;
    }
    

    And changing it to any implementation in the DI container.

    Let's say you have a Controller with 10 actions.

    Case 1 Is not the OOP way, because the call doesn't go through the DI container at all.

    Case 2 is actually OK, but you'll have to call the App facade in every action. It's not really beautiful.

    Case 3 gives you only one place to create/change/configure the class.

    E.g. you need to do something like:

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
        $this->userRepository->excludeAdmins();
    }
    

    A lot of repositories in constructor is actually ok, however if the code fills gross to you, you can extract it to a Service class.

    UPDATE By Service class I mean a class that doesn't extends anything and contains the business logic.

    Further reading: https://m.dotdev.co/design-pattern-service-layer-with-laravel-5-740ff0a7b65f

    Case 4. Facades, in my opinion, are suitable for something more global. Why would you want to populate each repository with a facade? Too time consuming.

    Case 5. Didn't get the question. You mean put it to the root namespace? What does it change?