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:
- Automatically detect dependencies in constructors
- If you need to build this dependency
- Creating objects through constructors to form dependencies
Let's take a very simple example.
1 <?php 2 namespace App\Http\Controllers; 3 use App\User; 4 use App\Repositories\UserRepository; 5 use App\Http\Controllers\Controller; 6 class UserController extends Controller 7 { 8 protected $userRepository; 9 public function __construct(UserRepository $userRepository) 10 { 11 $this->userRepository = $userRepository; 12 } 13 public function show($id) 14 { 15 $user = $this->userRepository->find($id); 16 return view('user.profile', ['user' => $user]); 17 } 18 }
Suppose you have a UserController class that requires UserRepository as a constructor dependency.
- The service container uses PHP's Reflection class To detect, the fact user repository needs to be resolved first.
- It then constructs an instance of UserRepository.
- It then constructs an instance of the UserController class.
How dependencies are resolved and injected, I'm confused by the fact that many Laraway 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.
1 <?php 2 $container->bind('My\Service', function($container) { 3 return new My\Service($container->make('My\AnotherService')); 4 });
You need to create a service provider to register the above services.
1 <?php 2 namespace App\Providers; 3 use Illuminate\Support\ServiceProvider; 4 class MyServiceProvider extends ServiceProvider 5 { 6 public function register() 7 { 8 $this->app->singleton(\My\Service::class, function ($app) { 9 return new \My\Service($app->make('My\AnotherService')); 10 }); 11 } 12 }
When My\Service needs to be parsed, the callback function responsible for returning an object will be called.
1 <?php 2 namespace App\Http\Controllers; 3 use App\User; 4 use App\Http\Controllers\Controller; 5 class MyController extends Controller 6 { 7 protected $myService; 8 public function __construct(\My\Service $myService) 9 { 10 $this->myService = $myService; 11 } 12 // .. Method 13 }
Real examples
Suppose your application needs the PHP SDK of Facebook to access the Facebook API, and your controller is like this:
1 <?php 2 namespace App\Http\Controllers; 3 use App\User; 4 use App\Http\Controllers\Controller; 5 use Facebook\Facebook; 6 class FacebookApiAccessController extends Controller 7 { 8 protected $facebook; 9 public function __construct(Facebook\Facebook $facebook) 10 { 11 $this->facebook = $facebook; 12 } 13 //.. action methods here 14 }
Now, you need to tell the Service Container how to build an instance of Facebook
1 <?php 2 $container->singleton('Facebook\Facebook', function() { 3 return new \Facebook\Facebook([ 4 'app_id' => config('services.facebook.app_id'), 5 'app_secret' => config('services.facebook.app_secret'), 6 'default_graph_version' => 'v2.10', 7 ]); 8 });
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 to simplify the creation of objects in Laravel. By default, the service container of Laravel will automatically use reflection to detect and resolve the dependency. However, you can specify a callback to resolve the service