---
layout: documentation
current_menu: v4
---

# Migrating from PHP-DI 3.x to 4.0

PHP-DI 4.0 is a new major version that comes with backward compatibility breaks.

This guide will help you migrate from a 3.x version to 4.0.


## Definitions

The biggest BC break is between the definitions format. The new definition format is very different from the old one,
because it is based on function helpers, not an array or YAML structure.

To be clear: YAML configuration is not supported anymore.

Here is a comparison:

```php
// Before
return [
    'My\Class' => [
        'constructor' => [
            'host' => 'db.host',
            'port' => 'db.port',
        ],
        'methods' => [
            'setFoo' => [ 'My\Foo' ],
        ],
    ],
];

// After
return [
    'My\Class' => DI\object()
        ->constructor(DI\link('db.host'), DI\link('db.port'))
        ->method('setFoo', DI\link('My\Foo'))
];
```

You may or may not like this choice, but this is the conclusion of a lot of thinking and trials.
If you are interested, you can read more here: [Thoughts about PHP-DI 4.0](https://gist.github.com/mnapoli/6890585),
the main reason is that offering a YAML DSL is very restrictive over what we can do with PHP code,
mainly **closures**.

We actually recommend that any complex definition should be written in PHP code using an anonymous function:

```php
return [
    MyClass::class => DI\factory(function (ContainerInterface $c) {
        $o = new MyClass($c->get('db.host'), $c->get('db.port'));
        $o->setFoo($c->get(Foo::class));
        return $o;
    })
];
```

Using real PHP code is of course better, because it's easier to maintain, it is less tied to PHP-DI and it's
not limited by an API.

On the other hand, the helper functions are helpful if you are writing a simple definition.

## Creating the container

You are encouraged to use the `ContainerBuilder` to create the `Container` if you weren't already doing this.

The API of the `ContainerBuilder` has changed a bit:

- `setDefinitionsValidation` has been removed (since it's PHP code it's validated by PHP)
- `addDefinitionsFromFile` is now `addDefinitions` and now takes a file name (simpler)
- `useReflection` is now `useAutowiring`


## Lazy injection and proxies

The way lazy injection and proxies work has been greatly simplified.

Now it is pretty simple: to use lazy injection, **you have to define an entry as "lazy"**.

You can **no longer** request a proxy using `$container->get('my.entry', $lazy = true)`, or with annotations:

```php
class Example {
    /**
     * @Inject(lazy=true)
     * @var Foo
     */
    protected $property1;
}
```

You can now do this:

```php
/**
 * @Injectable(lazy=true)
 */
class Foo {
}
```

Or

```php
<?php

return [
    'foo' => DI\object('MyClass')
        ->lazy(),
];
```

Read more in the [lazy injection documentation](../lazy-injection.md).


## Caches

That may be obvious, but remember to **clear the cache** when migrating an application from 3.x to 4.0.
PHP-DI may have cached definitions in the 3.x format, and v4 cannot read them.

You will have to clear the cache just once, when you install you application with the new PHP-DI version.


## Autoloading

If you use Composer, you have nothing to worry about. However if you use your own autoloader, you will
need to include this file manually: `php-di/src/DI/functions.php`.

This file contains the helper functions that you can use to define entries. And since there is no function
autoloading in PHP (yet), this file must be included manually.
