-->

Dependency Injection in Laravel 5 Package To Use o

2019-06-04 19:53发布

问题:

I am developing a package for Laravel 5, I decided to benefit from dependency injection in my package when using the Core classes of Laravel, but after reading more and also having asked this question Best approach for Dependency Injection in Laravel 5 package

Now I came up with the idea that if we are using Facades so much and calling static methods like FaceadeName:nameOfMethod the Container actually creates an object for us and calls its method, so to some extend using dependency injection for laravel for classes which are also available through the Facades are is almost useless.

For example having this class:

class MyController extends \App\Http\Controllers\Controller
{        
  public $text;
  public $lang;

 public function __construct()
 {         
   // Some codes here                            
}

public function myFunction(){
   $this->text = \Lang::get('package::all.text1');           
 }
}

doing this:

 App::bind('lang', function($app)
 {
    return new \Lang();
  });    

and then in the function:

public function myFunction()
{
    $lang = \App::make('lang');       
    $this->text = $lang::get('package::all.text1');           
}

is almost useless because we bind something to container that is already bound there

It is not a great idea to change the myFunction to

 public function myFunction(\Lang $lang){
     $this->text = $lang::get('package::all.text1');           
 }

as well, it might look like method injection but it doesn't bring so much advantages. Therefore it would be better not to use dependency injection for Facades in Laravel. Please let me know if I am right or not and please argue my opinion with the right answer if I am wrong.

回答1:

Facades provide a way of accessing the container through a class, so when you're accessing \Lang::function() you're actually calling app('translator')->function(). So in you're above example when you're binding the Lang facade into the container, you've then bound it twice, which isn't quite what you want.

All Laravel's functionality is already bound into the container and can be accessed by calling app('object'). You can see all the bindings here http://laravel.com/docs/5.0/facades

For dependency injection, you shouldn't be trying to inject the facades, but rather the classes the facades are already referencing. So for example, the \Lang facade references Illuminate\Translation\Translator which is bound to the container as translator

In your classes you can do the following

use App\Http\Controllers\Controller;
use Illuminate\Translation\Translator;

class MyController extends Controller
{
    protected $translator;

    // Dependency injection example
    public function __construct(Translator $translator)
    {
        $this->translator = $translator;
    }

    public function index()
    {
        $text = $this->translator->get('package::all.text1');
    }

    // Method injection example
    public function myFunction(Translator $translator)
    {
        $text = $translator->get('package::all.text1');
    }
}