How does Laravel 5 do so that an instance is passed automatically if we only define the Type Hinting in the parameter in a function?

4

I think this is a totally valid curiosity, as it greatly facilitates and speeds development.

I often analyze the framework code I usually use, such as Cakephp 2 , Laravel 4 and Symfony 2 .

I started working shortly with Laravel 5 and realized that there is a functionality in it that I have never seen in any of the frameworks. It is the automatic passing of an instance to the argument of a method of a controller or route, or any other class of the framework, simply by setting the Type Hiting of the function.

Example:

class AuthController extends Controller
{
    public function getIndex(Request $request, UrlGenerator $url)
    {
       $request->get('nome');
    }
}

When you do this in the parameters of getIndex , you automatically pass this to the method instances of the classes. So, if I do not want to use UrlGenerator , I can simply remove the parameter declaration from this method, it will not be passed by argument.

That is, no matter the position of the parameters, it always gives me the instance of the typed argument simply because I passed it there.

Another example:

 public function getIndex($id, Request $request){}

Or

public function getIndex(Request $request, $id) {}

How can I do this in php? How does Laravel do this?

    
asked by anonymous 02.03.2016 / 12:52

1 answer

3

This is only possible thanks to Laravel's Service Container . It is an implementation of IoC patterns Inversion of Control and Dependency Injection objective to reduce the coupling between classes and facilitate the construction of objects.

It resolves classes in two ways: Through a binding , which is a kind of configuration where we tell you which instance should be returned if given class is injected:

<?php 

app()->bind(MinhaClasse::class, function () {
    return new MinhaClasse(new OutraClasse, 'algum-argumento');
});

Basically here we are registering in the Service Container what it should return when instantiating a specific class. This can be used to bind a specific implementation of an Interface in our code. These bindings are usually written in Laravel's Service Provider classes.

The second form is similar to the first and Laravel uses the Refletion API of PHP to instantiate these classes. However this will not work with Interfaces and with classes that have constructor dependencies that can not be resolved either by the Service Container (a string ) with the API key, or an interface without binding for example).

This makes it possible for all classes that are inside to inject at the time of class instantiation the required dependencies.

Basically, Laravel uses the Service Container and requests that class. Underneath the cloths Laravel actually does this:

<?php 

app()->make(MinhaClasse::class);

This way of working is not unique to Laravel. There are other Dependency Injection implementations in other frameworks, such as Zend / Di / a> or the thephpleague / container .

To get an idea of how to do, you can be inspired by this class: link

    
02.03.2016 / 18:47