---
layout: documentation
current_menu: v5
---

# Migrating from PHP-DI 4.x to 5.0

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

This guide will help you migrate from a 4.x version to 5.0. It will only explain backward compatibility breaks, it will not present the new features (read the release notes or the blog post for that).

## Package name

PHP-DI has moved:

- to the new [PHP-DI](https://github.com/PHP-DI) organization on GitHub: [github.com/PHP-DI/PHP-DI](https://github.com/PHP-DI/PHP-DI)
- from `mnapoli/php-di` to [`php-di/php-di`](https://packagist.org/packages/php-di/php-di) on Packagist

While upgrading, you should change your `composer.json` to require `php-di/php-di`. Rest assured that you can still install older versions with `mnapoli/php-di` (backward compatibility is kept).

## PHP version requirement

PHP-DI 5 requires a PHP version greater or equal than **5.4** (was previously 5.3).

## Container

`DI\ContainerInterface` was deprecated since v4.1 and has been removed. It was replaced by [the standard `Interop\Container\ContainerInterface`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php).

## Definitions

### Annotations

Annotations are now disabled by default. If you use annotations, simply enable them in your config:

```php
$builder = new ContainerBuilder();
$builder->useAnnotations(true);

$container = $builder->build();
```

And install the Composer dependency by running:

```
composer require doctrine/annotations
```

### DI\link()

The `DI\link()` function helper has been deprecated (but still works). The reason for this is that when importing the function in PHP 5.6 with `use function DI\link`, it conflicts with [PHP's native `link()` function](http://php.net/link). This was a silly oversight when designing PHP-DI 4, sorry about that :)

`DI\get()` has been introduced as a replacement and is preferred over `DI\link()` (which still works). It has the advantage of being shorter and more explicit:

```php
return [
    EntityManager::class => DI\object(...),

    // Preferred version
    'entity_manager' => DI\get(EntityManager::class),
    // Deprecated but still works
    'entity_manager' => DI\link(EntityManager::class),

    // Example in an object definition:
    'MyClass' => DI\object()
        ->constructor(DI\get('SomeDependency')),
];
```

If you are using PHP 5.6 you can opt for the shorter (and awesome) syntax:

```php
use function DI\get;
use function DI\object;

return [
    'entity_manager'     => get(EntityManager::class),
    EntityManager::class => object()
        ->constructor(get('SomeDependency')),
];
```

### Factories

Closures are now considered as factories automatically:

```php
return [
    'foo' => DI\factory(function () {
        return new Foo();
    }),
    // can now be shortened to:
    'foo' => function () {
        return new Foo();
    },
];
```

If you defined a closure as a value (e.g. to have the closure injected in a class), you need to wrap the closure with the new `DI\value()` helper:

```php
    // the closure will be injected instead of being called
    'foo' => DI\value(function () {
        return new Foo();
    }),
```

### Scopes

The internal implementation of scopes has been simplified: this results in one less Composer dependency and better performances. Backward compatibility is kept so you don't have to change anything, however if you want you can replace the use of static methods (which might be deprecated in the future) with the constants.

Before:

```php
return [
    'MyClass' => DI\object()
        ->scope(Scope::PROTOTYPE()), // static method
];
```

After:

```php
return [
    'MyClass' => DI\object()
        ->scope(Scope::PROTOTYPE), // constant
];
```

Again, this change is optional, the static methods still work.

## Lazy injection

The [ProxyManager](https://github.com/Ocramius/ProxyManager) package comes with a lot of dependencies and is only useful only for lazy injection. This package is not installed by default in v5.0 in order to lighten PHP-DI's dependencies.

If you want to use **lazy injection**, you now need to install it explicitly:

```
composer require "ocramius/proxy-manager:~1.0"
```

Read more in [#198](https://github.com/PHP-DI/PHP-DI/issues/198) or in the [Lazy Injection documentation](../lazy-injection.md).

## Caching

### Caching library

The `doctrine/cache` library isn't required by PHP-DI by default anymore (in order to make the package lighter). If you set up a cache for PHP-DI, you need to require it:

```
composer require doctrine/cache
```

### Caching and dynamic definitions

*Note: this section might look complicated and confusing to you: it concerns a change for an edgy use case and you probably don't have to worry about this*.

Caching works the same in PHP-DI 5, however it is no longer possible to add *definitions* to a container on the fly **when using a cache**:

```php
$builder = new ContainerBuilder();
$builder->setDefinitionCache(new ApcCache());
$container = $builder->build();

// This still works: you can set values
$container->set('foo', 'hello');
$container->set('bar', new MyClass());

// This doesn't work anymore: you can't set definitions using ->set() when using a cache
$container->set('foo', DI\object('MyClass'));
```

The reason for this is that definitions are cached (not values). If you set a definition dynamically, then it will be cached, which could lead to very weird bugs (because dynamic definitions should of course not be cached since they are… dynamic).

The conclusion is: if you are using a cache, all you definitions should be static, i.e. you should add them to the `ContainerBuilder`:

```php
$builder = new ContainerBuilder();
$builder->setDefinitionCache(new ApcCache());

// Good
$builder->addDefinitions('file.php');
$builder->addDefinitions([
    'foo' => DI\object('MyClass'),
]);
```

Be reassured however that everything still works when you are not using a cache:

```php
$container = ContainerBuilder::buildDevContainer();

// All of this still works
$container->set('foo', 'hello');
$container->set('bar', new MyClass());
$container->set('baz', DI\object('MyClass'));
```

## Internal changes

If you were overriding or extending some internal classes of PHP-DI, be aware that they may have changed. For example definition sources have been refactored into a much simpler design.
