Mastering Dependency Injection Containers in PHP: Constructors, Methods, and Bindings
This guide explains how PHP dependency injection containers work, covering constructor, method, and setter/property injection, as well as binding classes, identifiers, closures, and interfaces in frameworks like ThinkPHP and Yii2, with clear code examples for each technique.
Common Injection Methods
Constructor Injection
When a class constructor is type‑hinted, the DI container resolves each parameter by retrieving the required class or interface instance and injecting it during object creation.
class Foo {
public function __construct(Bar $bar) {}
}
$foo = $container->get('Foo'); // equivalent to:
$bar = new Bar();
$foo = new Foo($bar);Method Injection
Method injection supplies dependencies only to a specific method, avoiding the overhead of passing them through the constructor when they are needed by a single method.
class MyClass extends \yii\base\Component {
public function __construct($config = []) {}
public function doSomething($param1, \my\heavy\Dependency $something) {
// use $something
}
}Setter and Property Injection
Setter/property injection is configured so the container can inject dependencies via public setters or properties after the object is created.
use yii\base\BaseObject;
class Foo extends BaseObject {
public $bar;
private $_qux;
public function getQux() { return $this->_qux; }
public function setQux(Qux $qux) { $this->_qux = $qux; }
}
$container->get('Foo', [], [
'bar' => $container->get('Bar'),
'qux' => $container->get('Qux'),
]);Direct Class Binding to the Container
ThinkPHP: Bind a Class Directly
// Bind class identifier
Container::getInstance()->bindTo(GameService::class);
// Automatic instantiation
$obj = Container::get(GameService::class);
// Quick call
halt($obj->test());ThinkPHP: Helper Function
// Bind class identifier
bind(GameService::class);
// Automatic instantiation
$obj = app(GameService::class);
halt($obj);Yii2: Register a Same‑Name Dependency
$container = new \yii\di\Container;
// Register the class; the name can be omitted because it matches the class name
$container->set(GameService::class);Binding an Identifier
ThinkPHP: Bind a Unique Identifier to an Existing Class
// Bind identifier
Container::getInstance()->bindTo('game_service2', GameService::class);
// Automatic instantiation
$obj = Container::get('game_service2');
halt($obj);ThinkPHP: Helper Function
// Bind identifier
bind('game_service', GameService::class);
// Automatic instantiation
$obj = app('game_service');
// Instantiation with parameters
$obj = app('game_service', ['file']);
halt($obj->test());Yii2: Register an Alias
$container = new \yii\di\Container;
$container->set('foo', 'yii\db\Connection');
// Create a Connection instance
$obj = $container->get('foo');Binding a Closure
ThinkPHP Usage
// Helper function
bind('sayHello', function($name) {
return 'hello,' . $name;
});
echo app('sayHello', ['thinkphp']);
// Container binding
Container::getInstance()->bindTo('sayTinywan', function($age) {
return 'Tinywan is ' . $age;
});
echo Container::get('sayTinywan', [24]);Yii2: Register a PHP Callback
// Callback executed each time $container->get('db') is called
$container->set('db', function($container, $params, $config) {
return new \yii\db\Connection($config);
});Binding a Class to an Interface
// Bind LoggerInterface to its implementation Log
bind('think\\LoggerInterface', 'think\\Log');Using an interface as a type hint for dependency injection:
<?php
namespace app\index\controller;
use think\LoggerInterface;
class Index {
public function hello(LoggerInterface $log) {
$log->record('hello,world!');
}
}Or via the container:
// Bind DriverInterface to YoungDriver and resolve Car
$driver = Container::getInstance()->bindTo(DriverInterface::class, YoungDriver::class);
$car = Container::get(Car::class, [$driver]);
var_dump($car->run());Service Locator
Provider Configuration (provider.php)
return [
'game_player' => \app\common\repositories\player\Game::class,
'random' => \app\common\repositories\game\RandomGroup::class,
];Resolving Services
// Bind a player interface to a concrete implementation
Container::getInstance()->bindTo(PlayerInterface::class, TeacherPlayer::class);
// Resolve the game service
$game = app('random');
// Resolve the player service
$player = app('game_player');
// Player starts the game
halt($player->play($game));Passing Parameters to Services
// Bind a different player implementation
Container::getInstance()->bindTo(PlayerInterface::class, StudentPlayer::class);
$game = app('random');
$parms = ['caode' => 200, 'name' => 'Tinywan'];
$player = app('game_player', ['ddd']);
// Player starts the game with additional parameters
halt($player->play($game, $parms));Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
