当前位置: 首页 > news >正文

PHP-DI版本迁移完整指南:从旧版本平滑升级到PHP-DI 7.0

PHP-DI版本迁移完整指南:从旧版本平滑升级到PHP-DI 7.0

【免费下载链接】PHP-DIThe dependency injection container for humans项目地址: https://gitcode.com/gh_mirrors/ph/PHP-DI

PHP-DI是一款为人类设计的依赖注入容器,它能够帮助开发者更轻松地管理类之间的依赖关系。随着PHP-DI 7.0的发布,带来了许多新特性和改进,但也有一些不兼容的变更。本指南将详细介绍从旧版本平滑升级到PHP-DI 7.0的步骤和注意事项,让你的项目能够顺利享受到新版本带来的好处。

为什么要升级到PHP-DI 7.0?

PHP-DI作为一款流行的依赖注入容器,不断地进行更新和优化。7.0版本不仅带来了性能上的提升,还引入了对PHP 8.0及以上版本特性的支持,如原生属性等。此外,随着用户数量的不断增长,社区的支持和维护也更加活跃,升级到新版本可以获得更好的稳定性和安全性。

升级前的准备工作

在开始升级之前,有一些准备工作需要完成,以确保升级过程的顺利进行。

检查PHP版本

PHP-DI 7.0要求PHP 8.0或更高版本。如果你的项目当前使用的是低于8.0的PHP版本,需要先升级PHP环境。你可以通过运行以下命令来检查当前PHP版本:

php -v

备份项目代码和配置

在进行任何升级操作之前,强烈建议备份你的项目代码和相关配置文件,以防止意外情况导致数据丢失。你可以使用版本控制工具(如Git)进行备份,或者手动复制项目文件到安全的位置。

检查依赖关系

查看项目中是否有其他依赖库与PHP-DI 7.0存在冲突。可以通过查看composer.json文件中的依赖项,并查阅相关库的文档,确认它们是否支持PHP-DI 7.0。

从不同版本升级的具体步骤

从PHP-DI 6.x升级到7.0

PHP版本要求

PHP-DI 7.0 now requires PHP 8.0 or greater. If you are using an older version, you can of course still use PHP-DI 6.

容器创建方式

The container can now be created with sane defaults without using theContainerBuilderclass (though it's not mandatory):

$container = new \DI\Container(); // With definitions: $container = new \DI\Container([ \Psr\Log\LoggerInterface::class => get(MyLogger::class), ]);

Related to that:\DI\ContainerBuilder::buildDevContainer()method is now obsolete and has been removed. Replace it with:

- $container = \DI\ContainerBuilder::buildDevContainer(); + $container = new \DI\Container();
注解(@Inject)替换为PHP属性(#[Inject]

Now that PHP 8.0 and up supports attributes natively, these are read instead of phpdoc annotations.

Additionally, now that PHP supports typed properties, PHP-DI will stop reading types from phpdoc.

Here is an example on how to migrate from PHP-DI 6 to PHP-DI 7:

  • before:
// Container configuration $containerBuilder = new \DI\ContainerBuilder; $containerBuilder->useAnnotations(true);
class Example { /** * @Inject * @var Foo */ private $property; /** * @Inject * @param Foo $param */ public function method($param) { } }
  • after:
// Container configuration $containerBuilder = new \DI\ContainerBuilder; $containerBuilder->useAttributes(true);
use DI\Attribute\Inject; class Example { #[Inject] private Foo $property; #[Inject] public function method(Foo $param) { } }

Note: remember to import the attribute class viause DI\Attribute\Inject;.

Read more about attributes in the PHP-DI documentation: PHP-DI attributes.

从PHP-DI 5.x升级到6.0

PHP版本要求

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

As a consequence if you requireocramius/proxy-managerin your project (to benefit from lazy injection), you must require v2.0 (not 1.0, which is not compatible with PHP 7).

Container-Interop和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 theInterop\Container\ContainerInterfacetype-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 use Interop\Container\ContainerInterface; return [ 'foo' => function (ContainerInterface $container) { return new Foo($container->get('bar')); }, // ... ];

Replaceuse Interop\Container\ContainerInterface;withuse Psr\Container\ContainerInterface;and you should be good to go.

定义相关变更
DI\object()

TheDI\object()function helper has been removed. You should useDI\create()orDI\autowire()instead.

What should you do with yourDI\object()definitions:

  • if you disabled autowiring:
    • replace it withDI\create()and everything should work
  • if you use autowiring:
    • replace it withDI\create()for definitions that replace autowiring completely (i.e. those that redefine all the parameters)
    • replace it withDI\autowire()for definitions that just definesomeparameters 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 toextendprevious definitions.create()andautowire()do not extend previous definitions, they completely override them, and this is intended. The behavior ofobject()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 thecreatefunction usinguse function DI\create as object;at the top of your configuration file.

DI\link()

TheDI\link()function helper was deprecated in 5.0. It is now completely removed. UseDI\get()instead.

嵌套定义和闭包

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

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

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 theDI\value()helper:

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, theprototypescope cannot be used anymore, thesingletonscope is now used everywhere.

Read more details and alternatives in the scopes documentation.

缓存

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, theContainerBuilder::setDefinitionCache()method was removed. In your code you can remove that line (and compile the container instead). Read the "performances" guide for more information.

编译容器

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.

从PHP-DI 4.x升级到5.0

包名称变更

PHP-DI has moved:

  • to the new PHP-DI organization on GitHub: github.com/PHP-DI/PHP-DI
  • frommnapoli/php-ditophp-di/php-dion Packagist

While upgrading, you should change yourcomposer.jsonto requirephp-di/php-di. Rest assured that you can still install older versions withmnapoli/php-di(backward compatibility is kept).

PHP版本要求

PHP-DI 5 requires a PHP version greater or equal than5.4(was previously 5.3).

容器接口变更

DI\ContainerInterfacewas deprecated since v4.1 and has been removed. It was replaced by the standardInterop\Container\ContainerInterface.

定义相关变更
注解

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()

TheDI\link()function helper has been deprecated (but still works). The reason for this is that when importing the function in PHP 5.6 withuse function DI\link, it conflicts with PHP's nativelink()function.

DI\get()has been introduced as a replacement and is preferred overDI\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')), ];
工厂

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 newDI\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 uselazy 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.

缓存
缓存库

Thedoctrine/cachelibrary 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
缓存和动态定义

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 adddefinitionsto a container on the flywhen 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).

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

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

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

升级后的测试与验证

升级完成后,需要对项目进行全面的测试,以确保所有功能都能正常工作。可以按照以下步骤进行测试:

运行单元测试

如果项目中有单元测试,运行所有的单元测试,检查是否有测试失败的情况。这可以帮助你快速发现升级过程中引入的问题。

手动测试关键功能

对于项目中的关键功能,进行手动测试,确保它们在新版本的PHP-DI下能够正常运行。例如,检查依赖注入是否正确,对象是否能够正常创建等。

检查日志和错误信息

在测试过程中,密切关注项目的日志文件和错误信息,及时发现并解决问题。

常见问题及解决方案

问题:升级后出现类找不到的错误

解决方案:检查是否正确安装了PHP-DI 7.0及其依赖项。可以通过运行composer installcomposer update来确保依赖项的正确安装。另外,检查命名空间和类名是否有拼写错误。

问题:属性注入(#[Inject])不生效

解决方案:确保在容器配置中启用了属性注入($containerBuilder->useAttributes(true);),并且正确导入了DI\Attribute\Inject类。同时,检查属性的访问修饰符是否为private,PHP-DI只支持对private属性进行注入。

问题:升级后性能下降

解决方案:PHP-DI 7.0引入了编译容器的功能,可以显著提高性能。参考性能文档,配置容器编译,以获得最佳性能。

总结

升级到PHP-DI 7.0可以为你的项目带来更好的性能、新的特性和更完善的支持。通过本指南的步骤,你可以顺利地从旧版本升级到PHP-DI 7.0。在升级过程中,记得做好备份工作,并进行充分的测试,以确保项目的稳定性。如果遇到问题,可以查阅官方文档或寻求社区的帮助。

希望本指南对你有所帮助,祝你升级顺利! 🚀

【免费下载链接】PHP-DIThe dependency injection container for humans项目地址: https://gitcode.com/gh_mirrors/ph/PHP-DI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.jsqmd.com/news/748330/

相关文章:

  • 汕头生腌店真的新鲜吗:潮汕生腌店/生腌海鲜店/金平生腌/龙湖生腌/龙眼南生腌/汕头生腌堂食/汕头生腌外卖/汕头生腌宵夜/选择指南 - 优质品牌商家
  • object-fit-images 与主流 polyfill 对比:为什么它是更好的选择?
  • 卡证检测矫正模型效果对比:默认阈值0.45 vs 低光0.35矫正质量
  • Eclipse在硬件设计中的高效应用与配置指南
  • Florr.io 新手必看:从Ant Egg到Mythic,一份超详细的生物掉落率与升级路线图
  • 终极指南:Tabby多语言支持方案——打造全球化AI编码助手
  • 2026年Q2国内酒店用瓷供应商排行及硬实力盘点:淄博中强瓷业有限公司联系电话/连锁餐饮店餐具谁家结实/镁质强化瓷/选择指南 - 优质品牌商家
  • 2026工业铝材厂家排行:断桥铝材/明框幕墙铝材/栏杆扶手铝材/流水线铝材/浴室门铝材/灶台铝材/百叶窗铝材/装饰线卡条铝材/选择指南 - 优质品牌商家
  • GameObject 常见类型详解 -- 陷阱(6:TRAP)
  • 第18篇:Vibe Coding时代:Prompt 版本管理与 A/B 测试实战,解决 Agent 改 Prompt 后效果忽好忽坏问题
  • DeepSeek-OCR-2快速部署:HuggingFace Spaces一键部署在线体验版
  • Vue 3项目里遇到‘Failed to resolve component‘警告?别慌,先检查你的import写法
  • 别再手动转录音频了!用FunASR的Paraformer-large模型,5分钟搞定几小时长音频的离线识别
  • IPProxyTool API接口完全指南:获取、删除、插入操作详解
  • 国产CPU固件开发笔记:在飞腾D2000的EDK2中调试I2C外设(以RTC为例)的完整流程
  • Python低代码配置性能瓶颈诊断:CPU飙升背后的YAML解析器陷阱与替代方案(压测数据全公开)
  • TinyFlow Session机制:深度学习图执行引擎内部原理
  • RLLM推理服务性能优化与部署实践
  • 基于开源大语言模型的本地Web聊天应用部署与实战指南
  • 3分钟极速安装安卓应用:APK-Installer完整指南
  • 如何构建企业级直播弹幕采集系统:WebSocket直连架构的完整解决方案
  • Talking Head Anime项目结构深度解读:从app到tha的模块化设计思想
  • 神经形态计算中的神经元参数推断与模拟推断技术
  • 终极指南:使用brew dispatch-build-bottle实现批量构建bottle的高效调度系统
  • Solid供应链管理终极指南:如何构建透明可追溯的去中心化系统
  • docker镜像下载的网址
  • AI元人文构想:发生学声明
  • Obsidian智能写作插件Scribe:提升Markdown编辑效率的自动化实践
  • RISE方法:机器人强化学习中的组合式世界模型与在线策略优化
  • 流媒体与视频监控技术基础:从视频采集到播放的全链路解析