1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
---
layout: documentation
title: Getting started
current_menu: getting-started
---
# Getting started with PHP-DI
Welcome! This guide will help you get started with using PHP-DI in your project.
Before beginning, you need to know what dependency injection is. If you don't, there's a whole article dedicated to it: [Understanding dependency injection](understanding-di.md).
## Installation
Install PHP-DI with [Composer](http://getcomposer.org/doc/00-intro.md):
```
composer require php-di/php-di
```
PHP-DI 7 requires PHP 8.0 or above.
## Basic usage
### 1. Use dependency injection
First, let's write code using dependency injection without thinking about PHP-DI:
```php
class Mailer
{
public function mail($recipient, $content)
{
// send an email to the recipient
}
}
```
```php
class UserManager
{
private $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function register($email, $password)
{
// The user just registered, we create his account
// ...
// We send him an email to say hello!
$this->mailer->mail($email, 'Hello and welcome!');
}
}
```
As we can see, the `UserManager` takes the `Mailer` as a constructor parameter: this is dependency injection!
### 2. Create the container
You can create a container instance pre-configured for development very easily:
```php
$container = new DI\Container();
```
If you want to register definition files (explained in [PHP definitions](php-definitions.md)) or tweak some options, you can use the [container builder](container-configuration.md):
```php
$builder = new DI\ContainerBuilder();
$builder->...
$container = $builder->build();
```
### 3. Create the objects
Without PHP-DI, we would have to "wire" the dependencies manually like this:
```php
$mailer = new Mailer();
$userManager = new UserManager($mailer);
```
Instead, we can let PHP-DI figure out the dependencies:
```php
$userManager = $container->get('UserManager');
```
Behind the scenes, PHP-DI will create both a Mailer object and a UserManager object.
> How does it know what to inject?
The container uses a technique called **autowiring**. This is not unique to PHP-DI, but this is still awesome. It will scan the code and see what are the parameters needed in the constructors.
In our example, the `UserManager` constructor takes a `Mailer` object: PHP-DI knows that it needs to create one. Pretty basic, but very efficient.
> Wait, isn't that weird and risky to scan PHP code like that?
Don't worry, PHP-DI uses [PHP's Reflection classes](http://php.net/manual/en/book.reflection.php) which is pretty standard: Laravel, Zend Framework and many other containers do the same. Performance wise, such information is read once and then cached, it has no impact.
## Defining injections
We have seen **autowiring**, which is when PHP-DI figures out automatically the dependencies a class needs. But we have 3 ways to define what to inject in a class:
- using [autowiring](autowiring.md)
- using [attributes](attributes.md)
- using [PHP definitions](php-definitions.md)
Every one of them is different and optional. Here is an example of PHP definitions in a file:
```php
return [
'api.url' => 'http://api.example.com',
'Webservice' => function (Container $c) {
return new Webservice($c->get('api.url'));
},
'Controller' => DI\create()
->constructor(DI\get('Webservice')),
];
```
Please read the [Defining injections](definition.md) documentation to learn about autowiring, attributes and PHP definitions.
## Framework integration
We have seen in the example above that we can use the container to get objects:
```php
$userManager = $container->get('UserManager');
```
However we don't want to call the container everywhere in our application: it would **couple our code to the container**. This is known as the *service locator antipattern* - or dependency *fetching* rather than *injection*.
To quote the Symfony documentation:
> You will need to get [an object] from the container at some point but this should be as few times as possible at the entry point to your application.
For this reason, PHP-DI integrates with some frameworks so that you don't have to call the container (dependencies are injected in controllers):
- [Symfony](frameworks/symfony2.md)
- [Slim](frameworks/slim.md)
- [Silex](frameworks/silex.md)
- [Zend Framework 2](frameworks/zf2.md)
- [Zend Expressive](frameworks/zend-expressive.md)
- [Silly](frameworks/silly.md)
If you want to use PHP-DI with another framework or your own code, try to use `$container->get()` in you root application class or front controller. Have a look at this [**demo application**](https://github.com/PHP-DI/demo) built around PHP-DI for a practical example.
## What's next
You can head over to [the documentation index](README.md). You can also read the [Best practices guide](best-practices.md), it's a good way to get a good view on when to use each of PHP-DI's features.
Here are some other topics that might interest you right now:
- [Configuring the container](container-configuration.md)
- [Defining injections](definition.md)
|