Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 IoC type-hinting not working

As far as I've understood, I should be able to type-hint my class instance arguments in the constructor of my class that I only instantiate with help of a Service Provider. Unfortunately I'm getting an error about missing arguments.

Tracker.php

function __construct($query, Tracker\Shipment $shipment) {
    $this->query    = $query;
    $this->shipment = $shipment;
}

TrackerServiceProvider.php

class TrackerServiceProvider extends \Illuminate\Support\ServiceProvider {
    public function register() {
        $this->app->bind('TrackerAPI',  function($app, $shipment_number) {
            return new Tracker\API($shipment_number); // omitting Shipment argument should resolve on its own?
        });
    }
}

Class API is extending Tracker, thus using its constructor. Why isn't it resolving without the implied class type hint?

like image 916
silkfire Avatar asked Feb 03 '15 23:02

silkfire


2 Answers

You've confused the PHP new functionality with Laravel's dependency injection via type hinting functionality.

In your TrackerAPI binding, when you specify return new Tracker\API($shipment_number);, there is nothing built into PHP to try to flesh out any missing parameters. To do this, you would need to return $app->make('Tracker\API', [$shipment_number]);

When you use the App::make() method, Laravel will do its magic to create a new object. It first checks for an explicitly defined binding. If it doesn't find an explicit binding, it will fall back to just using a combination of the supplied parameters plus type hints to create objects for any missing parameters.

Take the following statement: App::make('Tracker\API', [$shipment_number]). Assume there is no explicitly defined binding for Tracker\API. The Tracker\API constructor requires two parameters. $shipment_number is passed in in the parameter array, so it will be used as the first parameter. Since only one parameter was supplied, Laravel will App::make() the rest of the parameters using the type hints.

However, when you specifically instantiate the object yourself using the new keyword, none of this happens. It is a plain PHP object instantiation.

like image 121
patricus Avatar answered Sep 19 '22 23:09

patricus


Nope. Laravel can't resolve partials like that. You have to be explicit:

use Tracker\API;
use Tracker\Shipment;
use Illuminate\Support\ServiceProvider;

class TrackerServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('TrackerAPI',  function($app, $shipment_number)
        {
            return new API($shipment_number, $app[Shipment::class]);
        });
    }
}
like image 23
Joseph Silber Avatar answered Sep 19 '22 23:09

Joseph Silber