翻译进度
4
分块数量
1
参与人数

7.2. Migration from PHP-DI 4.x to 5.0

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


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:

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.

Definitions

Annotations

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

$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. 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:

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:

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:

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:

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

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

After:

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

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

Lazy injection

The 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 or in the Lazy Injection documentation.

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:

$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).

结论是:如果你使用缓存,则所有定义都应该是静态的,也就是说,你应该将它们添加到 ContainerBuilder

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

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

但是请放心,当你不使用缓存时一切都仍然有效:

$container = ContainerBuilder::buildDevContainer();

// 所有这些仍然有效
$container->set('foo', 'hello');
$container->set('bar', new MyClass());
$container->set('baz', DI\object('MyClass'));

内部变化

如果你要覆盖或扩展 PHP-DI 的某些内部类,请注意它们可能已更改。 例如,定义源已被重构为更简单的设计。

郁雁 翻译于 2年前

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~