Another way to analyze the dependency injection function of Laravel framework

Posted by The Midnighter on Wed, 30 Oct 2019 02:20:30 +0100

The article was forwarded from the professional Laravel developer community. Original link: https://learnku.com/laravel/t...

this StackOverflow answer It perfectly explains the concept of dependency injection.

Fundamentally speaking, dependency injection is not to let an object create a dependency, nor let a factory object create an object, but to turn the required dependency into an external object, making it a "someone's problem"

You inject class dependencies into "some people's problems." In Laravel, this "somebody" is Service container . In Laravel, the service container is responsible for injecting class dependencies through the constructor.

Whenever you request a dependency in a controller class, the service container is responsible for:

  1. Automatically detect dependencies in constructors
  2. If you need to build this dependency
  3. Creating objects through constructors to form dependencies

Let's take a very simple example.

<?php
namespace App\Http\Controllers;
use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
    protected $userRepository;
    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }
    public function show($id)
    {
        $user = $this->userRepository->find($id);
        return view('user.profile', ['user' => $user]);
    }
}

Suppose you have a UserController class that requires UserRepository as a constructor dependency.

  1. The service container uses PHP's Reflection class To detect, the fact UserRepository needs to be resolved first.
  2. It then constructs a UserRepository instance.
  3. It then constructs an instance of the UserController class.

How dependencies are resolved and injected, I'm confused that many Laravel developers don't know about this simple and powerful technology. This is a very powerful technology, which can be used to solve the dependency of complex objects.

If, for some reason, you don't want Laravel to automatically build an object, you can also tell Laravel Service Container how to construct the object by passing a callback that can be used to create a dependency.

<?php
$container->bind('My\Service', function($container) {
  return new My\Service($container->make('My\AnotherService'));
});

You need to create a service provider to register the above services.

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(\My\Service::class, function ($app) {
            return new \My\Service($app->make('My\AnotherService'));
        });
    }
}

When My\Service needs to be parsed, the callback function responsible for returning an object will be called.

<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class MyController extends Controller
{
    protected $myService;
    public function __construct(\My\Service $myService)
    {
        $this->myService = $myService;
    }
    // Method.
}

Real examples

Suppose your application needs the PHP SDK of Facebook to access the Facebook API, and your controller is like this:

<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
use Facebook\Facebook;
class FacebookApiAccessController extends Controller
{
    protected $facebook;
    public function __construct(Facebook\Facebook $facebook)
    {
        $this->facebook = $facebook;
    }
    //.. action methods here
}

Now, you need to tell the Service Container how to build an instance of Facebook.

<?php
$container->singleton('Facebook\Facebook', function() {
  return new \Facebook\Facebook([
    'app_id' => config('services.facebook.app_id'),
    'app_secret' => config('services.facebook.app_secret'),
    'default_graph_version' => 'v2.10',
  ]);
});

Notice that I've called the singleton method instead of bind. The only difference is that the service registered with singleton is cached, and the subsequent parsing service call returns the cached service.

conclusion

Dependency injection is a powerful technology that you can use in Laravel to simplify the creation of objects. By default, Laravel's service container will automatically use reflection to detect and resolve dependencies. However, you can specify callbacks to resolve services.

Topics: PHP Laravel SDK