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.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
Mastering Dependency Injection Containers in PHP: Constructors, Methods, and Bindings

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));
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PHPdependency-injectionConstructor InjectionSetter InjectionFrameworkMethod InjectionDI Container
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.