简体   繁体   中英

Binding to Laravel IoC instead of instantiating again and again

In my app I have a service called "LogService" to log events and other items. I basically need to use this on every controller to log events by users. Instead of having to instantiate this service in each controller, I had two thoughts for accomplishing this.

Option 1: Bind the service into the IoC and then resolve it that way

Option 2: Make a master class with the service in it and then extend it for other classes so they come with the service already bound

I have questions for each of these methods:

Option 1: Is this even possible? If so, would it just be with "App::make()" that it would be called? That way doesn't seem to play too well with IDE's

Option 2: I have done this kind of thing in the past but PHPStorm does not seem to recognize the service from the parent object because it is instantiated by "App::make()" and not through the regular dependency injection.

What would be the best course of action?

Thanks!

You can have it both ways, I think the neatest way would be:

1) Have an interface that describes your class, let's call it LogServiceInterface

2) Create a Service Provider that instantiates your class, like so:

<?php

 namespace App\Providers;

 use Illuminate\Support\ServiceProvider;

 class LoggerServiceProvider extends ServiceProvider
 {
     /**
      * Register bindings in the container.
      *
      * @return void
      */
     public function register()
     {
         $this->app->bind(LogServiceInterface::class, function($app)
         {
             return new LogService();
         });
     }
  }

3) Register this service provider in config/app.ph file:

'providers' => [
    // Other Service Providers

    App\Providers\LoggerServiceProvider::class,
],

4) Now, in controller you can request the instance of something that implements LoggerServiceInterface straight in the constructor:

(Some controller):

<?php namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use App\Repositories\OrderRepository;

class OrdersController extends Controller {

    /**
     * The logger service.
     * @var LoggerServiceInterface $loggerService
     */
    protected $loggerService;

    /**
     * Create a controller instance.
     *
     * @param  OrderRepository  $orders
     * @return void
     */
    public function __construct(LoggerServiceInterface $loggerService)
    {
        $this->loggerService = $loggerService;
    }

    /**
     * Show all of the orders.
     *
     * @return Response
     */
    public function index()
    {
        // $this->loggerService will be an instance of your LoggerService class that 
        // is instantiated in your service provider
    }

}

This way, you have got an easy way to quickly change the implementation of your service, moreover, Phpstorm can handle this very easily.

You will still be able to use app()->make() to obtain an instance of your service. This, however, will not be automatically picked up by Phpstorm. But you can help it to understand that, all you need to do is to use @var annotation, see:

/**
 * @var LoggerServiceInterface $logger
 */
 $logger = app()->make(LoggerServiceInterface::class);

That way, Phpstorm will know what to expect from that $logger object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM