DEPENDENCY INJECTION
As an example, the UserManager takes the Mailer as a constructor parameter.
This is dependency injection!
declare(strict_types=1);
class Mailer
{
}
class UserManager
{
private $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
}
$mailer = new Mailer();
$userManager = new UserManager($mailer);
If we add the pdo connection inside the method, to the class is coupled to both app and db.
This is messy!
class HelloWorld
{
...
public doSomething()
{
}
}
Add PDO as a dependency to the HelloWorld Class.
This lot cleaner, easier to understand and unit test.
declare(strict_types=1);
use ExampleApp\HelloWorld;
require_once __DIR__.'/../vendor/autoload.php';
$dsn = "mysql:host=localhost;dbname=sys;charset=utf8mb4;port=3306";
$pdo = new PDO($dsn, "admin", "password");
$obj = new HelloWorld($pdo);
$obj->test();
declare(strict_types=1);
namespace ExampleApp;
class HelloWorld
{
private $dbConnection;
public function __construct(\PDO $dbConnection)
{
$this->db = $dbConnection;
}
public function test()
{
echo "Hello World - autoload & PDO <br>";
$stmt = $this->db->query("SELECT * FROM sys_config");
while($row = $stmt->fetch()) {
var_dump($row);
}
}
}
CONTAINER
A dependency injection container wraps around your entire application.
It helps a lot as your application grows and became more complex.
One of the most popular DI container is PHP-DI.
composer require php-di/php-di
declare(strict_types=1);
use ExampleApp\HelloWorld;
use DI\ContainerBuilder;
use function DI\create;
use function DI\get;
require_once __DIR__.'/../vendor/autoload.php';
$containerBuilder = new ContainerBuilder();
$containerBuilder->useAutowiring(false);
$containerBuilder->useAnnotations(false);
$containerBuilder->addDefinitions([
HelloWorld::class => function() {
$dsn = "mysql:host=localhost;dbname=sys;charset=utf8mb4;port=3306";
$pdo = new PDO($dsn, "admin", "password");
return new HelloWorld($pdo);
}
]);
$container = $containerBuilder->build();
$obj = $container->get(HelloWorld::class);
$obj->test();
declare(strict_types=1);
namespace ExampleApp;
class HelloWorld
{
private $db;
public function __construct(\PDO $pdo)
{
$this->db = $pdo;
}
public function test() : void
{
echo "Hello World - autoloaded & PDO & DI <br>";
$stmt = $this->db->query("SELECT * FROM sys_config");
$row = $stmt->fetch();
echo $row['variable'];
}
}
This looks like a lot of extra fuss for what we already did.
The container will prove usefull when we add other tools to our application.