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:

// 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, 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:

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:

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:

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

You can now do this:

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

Or

<?php

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

Read more in the lazy injection documentation.

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.