Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best approach for Dependency Injection in Laravel 5 package

I am developing a package for Laravel 5, and now I need to benefit from dependency injection to have a more scalable and relaible application, I don't know which approach is the best to take and why, this is a piece of my code and I need to injected the Lang class dependency

 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');           
     }
}

In this link http://laravel.com/docs/4.2/ioc 2 approaches are suggested, Basic Usage and Automatic Resolution based on my understanding from the link taking the first approach I need to add

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

to the register part of application and then in the function I'll have something like this :

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

The other way is to modify the constructor like

  public function __construct(Lang $lang)
  {         
      $this->lang = $lang;
  }

And then instantiate object from Class like

  $myController = App::make('MyController');

Which way is the better way to take for, considering that this class is a Controller and it will be called in the routes file, or please correct me if my understanding from the link is not right. please also inform me why you suggest any of those approaches.

like image 331
Siavosh Avatar asked Mar 03 '15 14:03

Siavosh


People also ask

How do I perform dependency injection in Laravel?

In Laravel, dependency injection is the process of injecting class dependencies into a class through a constructor or setter method. This allows your code to look clean and run faster. Dependency injection involves the use of a Laravel service container, a container that is used to manage class dependencies.

Which is best dependency injection?

Constructor Injection This is the best method we have looked at so far. When using a constructor to set injected properties, you do not have to provide the autowire annotation.

Which method is used for dependency injection?

There are three main ways in which a client can receive injected services: Constructor injection, where dependencies are provided through a client's class constructor. Setter injection, where the client exposes a setter method which accepts the dependency.

Does Laravel utilize dependency injection?

Introduction. The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.


1 Answers

It should be noted that using local IoC resolution ($app->make() stylee) is not much better than using the facades directly (Lang::get() stylee) - you're still very much relying on Laravel's specific classes without really making your code explicitly state that it needs these exact classes. So the general advice is to, as much as possible, code to an interface if you want your code to be as portable as possible.

Of course there are a couple of big downsides to this currently in PHP development:

  1. These interfaces are not generally defined (except the PSR-3 LoggerInterface interface) so you still have to rely on a particular instance of the interface (in this case, Laravel's).
  2. If you decide to make your own generic interface (or the FIG eventually creates some of these), the classes that Laravel provides for translation (for example) don't implement it anyway, so you then need to subclass the existing ones just to make it look like it implements your own interface. But hey, that's the current best practice, so I guess if you wanna be using the current best practices, code to an interface, and don't worry for the time being that the interface you're coding to is Laravel-specific.

But anyway, here are my thoughts on your specific question. First off I should say that I haven't actually used Laravel 5 yet (just the 4s), but I have generally followed its development.

If the class I am coding will use a given dependency quite a lot or as a core part of how the class works I will use constructor dependency injection. Examples here are the Request or some Repository class in a controller, or a business logic class in a console command class.

If what I need I only need for a specific purpose (maybe redirecting from a controller and needing to generate a URI) I will resolve a local version from the IoC container ($this->app->make()) and then use that. If I were using Laravel 5 and the method was called by Laravel directly (e.g. a controller's action method) I may use method injection for this, I'm not 100% sure.

As a final note, the general advice is that if your constructor method signatures get too big due to a lot of dependencies:

  1. It's time to have a look at if your code relies too much on external dependencies. Maybe some of the functionality of your class can be extracted to its own class that splits the dependencies between the two.
  2. You should consider using setter methods rather than constructor injection - so instead of accepting a Request object, you have a $class->setRequest() method. The downside of doing this is that you need to tell Laravel's IoC container how to instantiate your object (i.e. that these setters must be called). It's not that big a deal but something worth noting.

Relevant links:

  • Laravel 5's IoC article
  • Laravel 5's Controller injection advice
like image 72
alexrussell Avatar answered Oct 05 '22 23:10

alexrussell