---
layout: documentation
current_menu: v6
---

# Migrating from PHP-DI 5.x to 6.0

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

This guide will help you migrate from a 5.x version to 6.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).

## PHP version

PHP-DI requires PHP 7 or greater, it is no longer compatible with PHP 5.

As a consequence if you require `ocramius/proxy-manager` in your project (to benefit from [lazy injection](../lazy-injection.md)), you must require v2.0 (not 1.0, which is not compatible with PHP 7).

## Container-Interop and PSR-11

PHP-DI 6 is compliant with PSR-11. Container-interop support has been dropped since container-interop has been replaced by PSR-11.

Most frameworks are now compatible with PSR-11 in their latest versions so there should be no migration step required on that side.

However it is possible you use the `Interop\Container\ContainerInterface` type-hint in your codebase. In that case, simply replace:

```
Interop\Container\ContainerInterface
```

with

```
Psr\Container\ContainerInterface
```

This might be the case for example in your PHP-DI configuration when using factories:

```php
<?php

use Interop\Container\ContainerInterface;

return [
    'foo' => function (ContainerInterface $container) {
        return new Foo($container->get('bar'));
    },
    // ...
];
```

Replace `use Interop\Container\ContainerInterface;` with `use Psr\Container\ContainerInterface;` and you should be good to go.

## Definitions

### DI\object()

The `DI\object()` function helper has been removed. You should use `DI\create()` or `DI\autowire()` instead.

**What should you do with your `DI\object()` definitions:**

- if you disabled autowiring:
    - replace it with `DI\create()` and everything should work
- if you use autowiring:
    - replace it with `DI\create()` for definitions that replace autowiring completely (i.e. those that redefine all the parameters)
    - replace it with `DI\autowire()` for definitions that just define *some* parameters and let autowiring guess the rest of the parameters

If you have a single configuration file, that's it.

If you have multiple configuration files, for example if you have built a module system, then there is one thing to be aware of: `DI\object()` used to *extend* previous definitions. `create()` and `autowire()` do not extend previous definitions, they completely override them, and this is intended. The behavior of `object()` was confusing and hard to understand, the new helpers are more predictable and simple.

*If you want a "quick and dirty" upgrade you can also alias the `create` function using `use function DI\create as object;` at the top of your configuration file.*

### DI\link()

The `DI\link()` function helper was deprecated in 5.0. It is now completely removed. Use `DI\get()` instead.

### Nested definitions and closures

Configuration files are now much more consistent: all definitions can be nested inside each other. You can nest `create()` definitions in arrays, `get()` in `env()`, etc.

Related to that, **closures are now always interpreted as "factory" definitions**, even if they are nested in another definition. For example:

```php
return [
    'db.name' => env('DB_NAME', function ($container) {
        // Computes a default value if the environment variable doesn't exist
        return $container->get('db.prefix') . '_foo';
    }),
    
    // is the same as:
    'db.name' => env('DB_NAME', factory(function ($container) {
        // Computes a default value if the environment variable doesn't exist
        return $container->get('db.prefix') . '_foo';
    })),
];
```

If you used anonymous functions for something else than factories in your configuration, you need to wrap them in the `DI\value()` helper:

```php
return [
    'router' => create(Router::class)
        ->method('setErrorHandler', value(function () {
            ...
        })),
];
```

Of course this applies only to closures that are inside your configuration files.

### Scopes

Scopes have been removed as they are out of the scope of a container. To be more clear, the `prototype` scope cannot be used anymore, the `singleton` scope is now used everywhere.

Read more details and alternatives in the [scopes](../scopes.md) documentation.

## Caching

Caching has been almost entirely removed in favor of a much faster alternative: compiling the container (see the section about compiling the container below).

As such, the `ContainerBuilder::setDefinitionCache()` method was removed. In your code you can remove that line (and compile the container instead). Read the ["performances" guide](../performances.md) for more information.

## Compiling the container

PHP-DI, like Symfony's container for example, can now be compiled to very optimized PHP code. That allows optimum performances for production environment. To compile the container read the ["performances" guide](../performances.md).

## Internal changes

If you were overriding or extending some internal classes of PHP-DI, be aware that they may have changed.
