# DI - Dependency Injection trong PHP (ok) 😁😁😁

[https://xuanthulab.net/di-dependency-injection-trong-php.html](https://xuanthulab.net/di-dependency-injection-trong-php.html)

{% embed url="https://php-di.org/doc/getting-started.html" %}

C:\xampp\htdocs\wpclidemo\index.php

```
<?php
require_once __DIR__ . '/vendor/autoload.php';
use DI\ContainerBuilder;
use User\User;
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(__DIR__ . '/config.php');
$container = $containerBuilder->build();
$user = $container->get(User::class);
```

C:\xampp\htdocs\wpclidemo\Database.php

```
<?php
// Database.php
namespace Database;
class Database {
  public function connect() {
    print('connected');
  }
}
?>
```

C:\xampp\htdocs\wpclidemo\User.php

```
<?php
// User.php
namespace User;
use Database\Database;
class User {
  private $database;
  public function __construct(Database $database) {
    $this->database = $database;
    $this->database->connect();
  }
}
```

C:\xampp\htdocs\wpclidemo\config.php

```
<?php
require_once __DIR__ . '/Database.php';
require_once __DIR__ . '/User.php';
use Database\Database;
use function DI\create;
use User\User;
return [
  'database' => create(Database::class),
  'user'     => create(User::class),
];
```

![](https://3988971916-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LXUV09EJOZ8BKB8YL5I%2Fuploads%2Fbs45yHZso5H17ZWnlAKV%2FScreenshot_1.png?alt=media\&token=cd85c714-2d0f-49cf-ad23-e1983976a6c7)

## A very basic guide to using PHP-DI for making DI Containers for your PHP applications with autowiring <a href="#id-2ad1" id="id-2ad1"></a>

There are lots of tutorials and guides online describing dependency injection and autowiring with PHP, but as someone who’s new to this whole concept and never even implemented a _dependency injection container_ I had a hard time getting started with using it in my PHP application. In this article, I want to give a very short and simple example of how to use PHP-DI to get started with a simple _DI container_.

## What is dependency injection? <a href="#id-596b" id="id-596b"></a>

Almost every PHP application consists of classes. We make objects and use those objects throughout our applications to tie all the logic together and make our applications work the way we want them to work, with our logic separated into classes. In order to use objects throughout our applications, we can choose to use dependency injection to pass objects around. A simple example of dependency injection:

**Our dependency which is a&#x20;**_**Database**_**&#x20;class that connects to a given database:**

```
// Database.phpnamespace Database;class Database{    public function connect() {        //...    }}
```

**Our&#x20;**_**User**_**&#x20;class which depends on the&#x20;**_**Database**_**&#x20;object to connect to a given database:**

```
// User.phpnamespace User;class User {    private $database;        public function __construct(Database $database) {        $this->database = $database;        $this->database->connect();    }}
```

**Now we can create a&#x20;**_**User**_**&#x20;object and inject the&#x20;**_**Database**_**&#x20;dependency into it in our&#x20;**_**index.php**_**:**

```
// index.php$user = new User(new Database());
```

What we have done is:

* We created a dependency, called _Database_. The _Database_ dependency currently can only do one thing, which is connecting to a database.
* We created a _User_ class. This class can only do on thing, which is getting user data. In order to do this, the _User_ class needs the _Database_ dependency to connect to the database.
* We created a _User_ object, and passed a _Database_ object (the dependency) to its constructor. By doing so, we’re injecting the _Database_ dependency into the _User_ object.

This looks nice, however, when your application gets more and more complicated, you end up passing around these objects from on place to another. This makes your code unreadable and hard to maintain. To fix this problem, we can use a **DI Container**, short for **Dependency Injection Container**. The DI Container is a single source of truth for all our dependencies and can automate the injection of dependencies throughout our code.

## Let’s implement a DI Container using PHP-DI <a href="#id-0d0d" id="id-0d0d"></a>

**Step 1: Let’s install PHP-DI using Composer**

```
composer require php-di / php-di
```

Now we’ve included PHP-DI in our project. See [https://php-di.org/](https://translate.google.com/website?sl=auto\&tl=en\&hl=vi\&client=webapp\&u=https://php-di.org/) for more information about PHP-DI.

**Step 2: Let’s modify our&#x20;**_**index.php**_**&#x20;and add a DI Container to it and create a&#x20;**_**User**_**&#x20;object with the&#x20;**_**Database**_**&#x20;dependency passed to it**

```
require_once __DIR__.'/vendor/autoload.php';use DI\ContainerBuilder;use User\User;$containerBuilder = new ContainerBuilder();$containerBuilder->addDefinitions(__DIR__.'/config.php');$container = $containerBuilder->build();$container->get(User::class);
```

On this line `$containerBuilder->addDefinitions(__DIR__.’/config.php’);` we’re referring to a file called **config.php**. This file contains a list of our _definitions_. Consider _definitions_ as being our _dependencies (_[https://php-di.org/doc/definition.html](https://translate.google.com/website?sl=auto\&tl=en\&hl=vi\&client=webapp\&u=https://php-di.org/doc/definition.html)).

**Step 3: Let’s create our config with a list of&#x20;**_**definitions/dependencies**_

```
require_once __DIR__.'/Database.php';require_once __DIR__.'/User.php';use Database\Database;use User\User;use function DI\create;return [  'database' => create(Database::class),  'user' => create(User::class)];
```

Here we require our classes at the top. Next, we import the _Database_ and _User_ classes. Last but not least, we return an array with our definitions. We use the _class_ magic constant, as is advised by the PHP-DI documentation ([https://php-di.org/doc/php-definitions.html#syntax](https://translate.google.com/website?sl=auto\&tl=en\&hl=vi\&client=webapp\&u=https://php-di.org/doc/php-definitions.html%23syntax)).

As we’re doing `$container->get(User::class);` in our **index.php** file, we’re instructing PHP-DI to employ autowiring. All dependencies will be loaded automatically, because the function signature of the _User_ class constructor looks as follows:

```
public function __construct(Database $database)
```

PHP-DI will see that the _User_ constructor requires a _Database_ object and will inject that dependency automatically into each _User_ object.

To tie it all together:

**index.php**

```
require_once __DIR__.'/vendor/autoload.php';use DI\ContainerBuilder;use User\User;$containerBuilder = new ContainerBuilder();$containerBuilder->addDefinitions(__DIR__.'/config.php');$container = $containerBuilder->build();$user = $container->get(User::class);
```

**User.php**

```
namespace User;use Database\Database;class User{  private $database;  public function __construct(Database $database)  {    $this->database = $database;    $this->database->connect();  }}
```

**Database.php**

```
namespace Database;class Database{  public function connect() {    print('connected');  }}
```

**config.php**

```
require_once __DIR__.'/Database.php';require_once __DIR__.'/User.php';use Database\Database;use User\User;use function DI\create;return [  'database' => create(Database::class),  'user' => create(User::class)];
```

Running this code, you should see the text “connected” on your screen. This means PHP-DI successfully injects the _Database_ dependency into the _User_ object and instantiates it.

With this simple example, you can start writing PHP code with a simple DI Container. Remember to add each dependency to the **config.php** and simply add your needed dependencies to the _constructor_ of each class where you have dependencies, and PHP-DI will handle the rest using autowiring. In order to make autowiring work, you have to create objects by NOT using the `new` keyword. Instead, use `$myObjWithDependencies = $container->get(myObjWithDependencies::class);` and PHP-DI will know to check the _constructor_ of _myObjWithDependencies_ and inject all needed dependencies automatically.
