web-dev-qa-db-fra.com

Dépendances insolubles résolvant [paramètre n ° 0 [<requis> $ nom]]

Attention: Cette question est spécifique à Laravel 4.

J'utilise Facades dans mes contrôleurs auparavant. Par conséquent, je sais que le code fonctionne. Maintenant, je dois introduire l'injection de dépendance pour diverses raisons.

Après refactorisation du contrôleur, l'erreur suivante apparaît:

Illuminate\Container\BindingResolutionException

Dépendance insoluble résolvant [paramètre n ° 0 [$ name]].

Je ne peux pas comprendre où est le problème. Le message d'erreur me semble cryptique et je ne le comprends pas. (Je ne vois aucun problème avec mes paramètres __constructor puisque j'ai enregistré la liaison pour la HelpersInterface)

Voici les parties importantes de mon code:

Fichier: app/start/global.php

<?php

// ...

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

Fichier: composer.json

// ...

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

// ...

Fichier: 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();
    }

}

Fichier: 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
    ) {
        // ...
    }

// ...

}

Fichier: 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']
        );
    });
}
16
Martin

Il semble que votre constructeur Acme\Services\Helpers prenne un paramètre $name, mais que le type ne soit pas indiqué.

Le CIO de Laravel n'est pas magique. Si vous ne fournissez pas d'indication de type pour chaque paramètre, le conteneur IoC n'a aucun moyen de savoir quoi transmettre.

17
Joseph Silber

Je l'ai réparé. Tous les tutoriels sur l'injection de dépendances faisaient référence à des implémentations concrètes d'interfaces, ce qui m'a amené à penser que c'était la solution. Joseph Silber's answer m'a mis sur la bonne voie.

L'astuce consiste à lier l'interface à la liaison de la ServiceProvider comme indiqué ci-dessous. De cette façon Laravel saura instancier le service Helpers.

Fichier: app/start/global.php

<?php

// ...

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

Pour moi, il ne s'agissait que de courir

php artisan optimize:clear
0
CIRCLE