Unresolvable dependency resolving [Parameter #0 [

2020-02-06 18:25发布

问题:

Warning: This question is Laravel 4 specific.

I've been using Facades in my controllers before. Therefore I know the code is working. Now I need to introduce dependency injection for various reasons.

After refactoring the controller I get following error:

Illuminate \ Container \ BindingResolutionException

Unresolvable dependency resolving [Parameter #0 [ $name ]].

I can't figure out where the problem is. The Error message seems cryptic to me and I don't understand it. (I don't see any problem with my __constructor parameters since I've registered the binding for the HelpersInterface)

Here are the important parts of my code:

File: app/start/global.php

<?php

// ...

App::bind('Acme\Interfaces\HelpersInterface', 'Acme\Services\Helpers');

File: composer.json

// ...

"autoload": {
    // ...
    "psr-0": {
        "Acme": "app/"
    }
},

// ...

File: app/Acme/Controllers/BaseController.php

<?php namespace Acme\Controllers;

use Carbon\Carbon;
use Controller;
use Illuminate\Foundation\Application as App;
use Illuminate\View\Factory as View;
use Acme\Interfaces\HelpersInterface as Helpers;
use Illuminate\Http\Response;

class BaseController extends Controller {

    /**
     * @var \Illuminate\Foundation\Application
     */
    private $app;

    /**
     * @var \Carbon\Carbon
     */
    private $carbon;

    /**
     * @var \Illuminate\View\Factory
     */
    private $view;

    /**
     * @var \Acme\Interfaces\HelpersInterface
     */
    private $helpers;

    function __construct(App $app, Carbon $carbon, View $view, Helpers $helpers)
    {
        $this->app = $app;
        $this->carbon = $carbon;
        $this->view = $view;
        $this->helpers = $helpers;

        $lang = $this->app->getLocale();
        $now = $this->carbon->now();

        $this->view->share('lang', $lang);
        $this->view->share('now', $now);
    }

    /**
     * Missing Method
     *
     * Abort the app and return a 404 response
     *
     * @param array $parameters
     * @return Response
     */
    public function missingMethod($parameters = array())
    {
        return $this->helpers->force404();
    }

}

File: app/Acme/Services/Helpers.php

<?php namespace Acme\Services;

use Illuminate\Config\Repository as Config;
use Illuminate\Database\Connection as DB;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector as Redirect;
use Illuminate\Session\Store as Session;
use Illuminate\Support\Facades\Response;
use Illuminate\Translation\Translator as Lang;
use Illuminate\View\Factory as View;
use Acme\Interfaces\MockablyInterface;
use Monolog\Logger as Log;

class Helpers implements HelpersInterface {

// ...

    public function __construct(
        Config $config,
        Lang $lang,
        View $view,
        MockablyInterface $mockably,
        Log $log,
        Request $request,
        Session $session,
        DB $db,
        Redirect $redirect,
        Response $response
    ) {
        // ...
    }

// ...

}

File: app/Acme/Providers/HelpersServiceProvider.php

<?php namespace Acme\Providers;

use Illuminate\Support\ServiceProvider;
use Acme\Services\Helpers;

class HelpersServiceProvider extends ServiceProvider {

private $db;
private $defaultDbConnection;

protected function init()
{
    $this->db = $this->app['db'];
    $this->defaultDbConnection = $this->db->getDefaultConnection();
}

public function register()
{
    $this->init();

    $this->app->bind('helpers', function ()
    {
        return new Helpers(
            $this->app['config'],
            $this->app['translator'],
            $this->app['view'],
            $this->app['mockably'],
            $this->app->make('log')->getMonolog(),
            $this->app['request'],
            $this->app['session.store'],
            $this->db->connection($this->defaultDbConnection),
            $this->app['redirect'],
            $this->app['Illuminate\Support\Facades\Response']
        );
    });
}

回答1:

It seems your Acme\Services\Helpers constructor takes a $name parameter, but is not type hinted.

Laravel's IoC is not magic. If your don't provide a type hint for every parameter, the IoC container has no way of knowing what to pass in.



回答2:

For me it was just a matter of running

php artisan optimize:clear


回答3:

Got it fixed. All the tutorials about dependency injection were referring to concrete implementations of interfaces so that I thought that's the way to go about it. Joseph Silber's answer got me on the right track.

The trick is to bind the Interface to the binding of the ServiceProvider like shown below. That way Laravel will know how to instantiate the Helpers service.

File: app/start/global.php

<?php

// ...

App::bind('Acme\Interfaces\HelpersInterface', 'helpers');