Short story: I can not get method injection working with Laravel container installed using composer (https://packagist.org/packages/illuminate/container). Injection only works if used in the constructor of objects. For example:
class SomeClass {
function __construct(InjectedClassWorksHere $obj) {}
function someFunction(InjectedClassFailsHere $obj) {}
}
Long story: I was looking at re-factoring a major project to using Laravel, but due to business pressure, I am not able to invest in the time I would like. In an effort to not throw the "baby out with the bath water", I am using the individual Laravel components to up the elegance of the code being developed in the old branch. One of my favourite new techniques I picked up when evaluating Laravel was the concept of dependency injection. I was delighted to find out later that I could use that OUTSIDE of a Laravel project. I now have this working and all is well, except the dev version of the container found online does not seem to support method injection.
Has anyone else been able to get the container to work and do method injection outside of a Laravel project?
My approach so far...
composer.json
"illuminate/support": "5.0.*@dev",
"illuminate/container": "5.0.*@dev",
Application bootstrap code:
use Illuminate\Container\Container;
$container = new Container();
$container->bind('app', self::$container); //not sure if this is necessary
$dispatcher = $container->make('MyCustomDispatcher');
$dispatcher->call('some URL params to find controller');
With the above, I am able to inject in constructors of my controllers, but not their methods methods. What am I missing?
Full source... (C:\workspace\LMS>php cmd\test_container.php)
<?php
// This sets up my include path and calls the composer autoloader
require_once "bare_init.php";
use Illuminate\Container\Container;
use Illuminate\Support\ClassLoader;
use Illuminate\Support\Facades\Facade;
// Get a reference to the root of the includes directory
$basePath = dirname(dirname(__FILE__));
ClassLoader::register();
ClassLoader::addDirectories([
$basePath
]);
$container = new Container();
$container->bind('app', $container);
$container->bind('path.base', $basePath);
class One {
public $two;
public $say = 'hi';
function __construct(Two $two) {
$this->two = $two;
}
}
Class Two {
public $some = 'thing';
public function doStuff(One $one) {
return $one->say;
}
}
/* @var $one One */
$one = $container->make(One);
var_dump($one);
print $one->two->doStuff();
When I run the above, I get...
C:\workspace\LMS>php cmd\test_container.php
object(One)#9 (2) {
["two"]=>
object(Two)#11 (1) {
["some"]=>
string(5) "thing"
}
["say"]=>
string(2) "hi"
}
PHP Catchable fatal error: Argument 1 passed to Two::doStuff() must be an instance of One, none
given, called in C:\workspace\LMS\cmd\test_container.php on line 41
and defined in C:\workspace\LMS\cmd\test_container.php on line 33
Catchable fatal error: Argument 1 passed to Two::doStuff() must be an instance of One, none
given, called in C:\workspace\LMS\cmd\test_container.php on line 41 and
defined in C:\workspace\LMS\cmd\test_container.php on line 33
Or, a more basic example that illustrates the injection working in a constructor but not a method...
class One {
function __construct(Two $two) {}
public function doStuff(Three $three) {}
}
class Two {}
class Three {}
$one = $container->make(One); // totally fine. Injection works
$one->doStuff(); // Throws Exception. (sad trombone)