Getting `Unresolvable dependency` exception
I'm using https://github.com/barryvdh/laravel-ide-helper to generate auto-complete for PhpStorm. I guess it's invoking all services providers to work. As a result I'm getting following exception:
Exception: Cannot instantiate Twig extension 'TwigBridge\Extension\Laravel\Form': Unresolvable dependency resolving [Parameter #2 [ <required> $csrfToken ]] in class Illuminate\Html\FormBuilder
Skipping \TwigBridge\Facade\Twig.
A new helper file was written to _ide_helper.php
I guess this happens because the mentioned TwigBridge\Extension\Laravel\Form class has dependency on FormBuilder (see https://github.com/rcrowe/TwigBridge/blob/master/src/Extension/Laravel/Form.php#L34), which happens to have 3rd required argument called $csrfToken: https://github.com/laravel/framework/blob/4.2/src/Illuminate/Html/FormBuilder.php#L82
Used Laravel Version: 4.3
Related issue: barryvdh/laravel-ide-helper#119
Same happens when I try to create twig file and use it:

I guess it's Laravel itself who is trying to inject dependencies and fails. If that $csrfToken argument was there all the time, then I wonder how this could be working at all.
It wasn't until 5.x
And as I said it doesn't have to do with the helper. Just publish the config and remove the form extension for now, until it's fixed, or create a PR to fix it.
If I'd only knew what was making it work in Laravel 4.2 in the first place knowing that constructor declaration of FormBuilder was the same all the time.
Not sure, the FormBuilder is created by the HtmlServiceProvider, so that instance should be passed on to the extension. You did include the HtmlServiceProvider right?
I've echoed some debug into in Container::getDependencies method (https://github.com/laravel/framework/blob/4.2/src/Illuminate/Container/Container.php#L549) in both Laravel version to see what's actually being resolved and here are the results:
Laravel 4.2:
→ artisan ide-helper:generate
[4.2, getDependencies] TwigBridge\Extension\Loader\Facades(config)
[4.2, getDependencies] TwigBridge\Extension\Loader\Filters(config)
[4.2, getDependencies] TwigBridge\Extension\Loader\Functions(config)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Auth(auth)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Config(config)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Form(form)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Html(html)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Input(request)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Session(session)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Translator(translator)
[4.2, getDependencies] TwigBridge\Extension\Laravel\Url(url)
A new helper file was written to _ide_helper.php
Laravel 4.3:
→ artisan ide-helper:generate
[4.3, getDependencies] App\Console\InspireCommand()
[4.3, getDependencies] TwigBridge\Extension\Loader\Facades(config)
[4.3, getDependencies] TwigBridge\Extension\Loader\Filters(config)
[4.3, getDependencies] TwigBridge\Extension\Loader\Functions(config)
[4.3, getDependencies] TwigBridge\Extension\Laravel\Auth(auth)
[4.3, getDependencies] TwigBridge\Extension\Laravel\Config(config)
[4.3, getDependencies] TwigBridge\Extension\Laravel\Form(form)
[4.3, getDependencies] Illuminate\Html\FormBuilder(html, url, csrfToken)
[4.3, getDependencies] Illuminate\Html\HtmlBuilder(url)
[4.3, resolveNonClass] Parameter #2 [ <required> $csrfToken ]
Exception: Cannot instantiate Twig extension 'TwigBridge\Extension\Laravel\Form': Unresolvable dependency resolving [Parameter #2 [ <required> $csrfToken ]] in class Illuminate\Html\FormBuilder
Skipping \TwigBridge\Facade\Twig.
A new helper file was written to _ide_helper.php
The major change between both Laravel versions is fact that in Laravel 4.3 the Html component was moved out from the core. It maybe affecting what's being inspected by Laravel during ide-helper run.
I've placed this in the beginning of getDependencies method:
$backtrace = debug_backtrace(0);
echo '[4.2, getDependencies] ' . $backtrace[1]['args'][0] . '(' . $this->getParameterNames($parameters) . ')' . PHP_EOL;
and added this helper method:
/**
* Returns names of parameters.
*
* @param array $parameters Parameters.
*
* @return string
*/
protected function getParameterNames(array $parameters)
{
$ret = array();
/** @var ReflectionParameter $parameter */
foreach ( $parameters as $parameter ) {
$ret[] = $parameter->name;
}
return implode(', ', $ret);
}
Here is the gist containing the config/app.php from both Laravel installations: https://gist.github.com/aik099/bfd82feb6c1680277500
If this is for laravel 5 (new name for 4.3), then the html stuff is setup wrong.
I found one post on a forum explaining how to connect back that HTML component that was removed from core in 4.3/5.0 : http://laravel.io/forum/09-20-2014-html-form-class-not-found-in-laravel-5 . I'm not sure if it's correct way of doing that because such migration wasn't mentioned in official docs.
Yeh. It's correct.
- https://github.com/illuminate/html/blob/master/HtmlFacade.php
- https://github.com/illuminate/html/blob/master/HtmlServiceProvider.php
If this is for laravel 5 (new name for 4.3), then the html stuff is setup wrong.
I guess you've looked at Gist I provided to say that it's something wrong with it.
Yeh. It's correct.
So what might be happening wrong when TwigBridge is connected?
Debugging a bit more revealed that in Laravel 4.2 by the moment the TwigBridge\Extension\Laravel\Form class is inspected that instance of FormBuilder is already created under form alias (Container::aliases) and it's being reused.
However in Laravel 4.3/5.0 there is no such alias as form at all and attempt to instantiate FormBuilder class directly is made.
Please stop saying 4.3/5.0. 4.3 doesn't exist. 5.0 will be the next version.
Please stop saying 4.3/5.0. 4.3 doesn't exist. 5.0 will be the next version.
I'm new to Laravel, so I wasn't sure what version to use because in forums people use both versions. Since everybody know that 4.3 is essentially 5.0, then no confusion happening anyway :wink:
I've updated gist with dump of aliases to the point where FormBuilder class is about to be inspected because of it's usage within TwigBridge\Form extension.
I'm on my phone so can't really check, but I think the form binding, as registered within the service provider was aliases to the FormBuilder class, in here: https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/Application.php (registerCoreContainerAliases or something) In 5.x that is probably removed, so you have to make the alias yourself. So either that should be a extra step in migrating or the service provider should take care of that.
Adding following to aliases array in config/app.php in Laravel 5.0 had no effect:
'form' => 'Illuminate\Html\FormBuilder',
'html' => 'Illuminate\Html\HtmlBuilder',
I've added them after
'Form' => 'Illuminate\Html\FormFacade',
'HTML' => 'Illuminate\Html\HtmlFacade',
Better to not use these aliases and just use the full class names to be honest,
But that's what I was doing initially and problem only came up when I tried to use TwigBridge. I'm kind of stuck at that point. I bet everybody attempting to use TwigBridge with Laravel 5.0 would be stuck as well.
Those are different aliases, I don't mean the facades. You have to register the binding 'form' as an alias to the FormBuilder, something like $app->alias('form', 'Illuminate\Html\FormBuilder') That way the app container knows it can resolve that shared binding when we ask for the FormBuilder.
I think I understand now why it worked in Laravel 4.2. The HtmlServiceProvider put a closure on form service name that would get current token from session and pass it as 3rd argument when creating service in https://github.com/laravel/framework/blob/4.2/src/Illuminate/Html/HtmlServiceProvider.php#L46
Thanks to the aliasing of FormBuilder to form whoever tried to instantiate FormBuilder were hitting that closure instead that filled-in that missing 3rd parameter ($csrfToken).
Now with Laravel 5.0 the form alias is gone so whoever has type hint of FormBuilder in the constructor (luckily it's the TwigBundle's Form class) tries to instantiate the FormBuilder class directly and doesn't hit designated form closure that HtmlServiceProvider registers.
Those are different aliases, I don't mean the facades. You have to register the binding 'form' as an alias to the FormBuilder, something like $app->alias('form', 'Illuminate\Html\FormBuilder')
Different aliases, I wasn't expecting that. I guess it's the service provider that needs to do that. So adding ``before https://github.com/laravel/framework/blob/4.2/src/Illuminate/Html/HtmlServiceProvider.php#L46 line (similar forregisterHtmlBuilder) should fix the problem:
$this->app->alias('form', 'Illuminate\Html\FormBuilder');
I think that providers should be doing that all the time and not having half of registration happen in provider and other half in the registerCoreContainerAliases method. That misplaced code revealed that problem when Html component was moved away from core.
By the way that fixed a problem.
But I'm unsure where to send a PR, because in master branch there is no such Html component anymore (https://github.com/laravel/framework/tree/master/src/Illuminate) and on the illuminate company on github all components are marked as read-only (https://github.com/illuminate/html).
@rcrowe , this should solved after both following PR's will be merged:
- illuminate/html#12
- illuminate/html#13
Hello,
aik099 I got it to work just applying your first PR and adding this to my app.php
...
'providers' => [
....
'Illuminate\Html\HtmlServiceProvider',
....
],
...
'aliases' => [
....
'Form' => 'Illuminate\Html\FormFacade',
'HTML' => 'Illuminate\Html\HtmlFacade',
....
],
...
Yes, then Unresolved dependency exception (during artisan usage) indeed go away after first PR merge. However if you try to actually create a twig template and view it then without 2nd PR you'll get same exception again.
Nope, Right now I'm rendering twig templates with form on them and everything works fine.
Sorry, but now stop working even with PR2 and without it. Something really weird.
Because you need to run artisan clear-complied and artisan optimize after changing stuff in config. At least I do. I guess if you change classes that go into compilation that makes sense.