PHP-DI版本迁移完整指南从旧版本平滑升级到PHP-DI 7.0【免费下载链接】PHP-DIThe dependency injection container for humans项目地址: https://gitcode.com/gh_mirrors/ph/PHP-DIPHP-DI是一款为人类设计的依赖注入容器它能够帮助开发者更轻松地管理类之间的依赖关系。随着PHP-DI 7.0的发布带来了许多新特性和改进但也有一些不兼容的变更。本指南将详细介绍从旧版本平滑升级到PHP-DI 7.0的步骤和注意事项让你的项目能够顺利享受到新版本带来的好处。为什么要升级到PHP-DI 7.0PHP-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.0PHP版本要求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 its 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.0PHP版本要求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-11PHP-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\ContainerInterfacewithPsr\Container\ContainerInterfaceThis 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 workif 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 parametersIf you have a single configuration file, thats 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 doesnt 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 doesnt 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.作用域ScopesScopes 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 Symfonys 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-DIfrommnapoli/php-ditophp-di/php-dion PackagistWhile 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/annotationsDI\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 PHPs 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(); }),作用域ScopesThe internal implementation of scopes has been simplified: this results in one less Composer dependency and better performances. Backward compatibility is kept so you dont 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 injectionThe 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-DIs dependencies.If you want to uselazy injection, you now need to install it explicitly:composer require ocramius/proxy-manager:~1.0Read more in #198 or in the Lazy Injection documentation.缓存缓存库Thedoctrine/cachelibrary isnt 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 dont 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 doesnt work anymore: you cant 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 install或composer update来确保依赖项的正确安装。另外检查命名空间和类名是否有拼写错误。问题属性注入#[Inject]不生效解决方案确保在容器配置中启用了属性注入$containerBuilder-useAttributes(true);并且正确导入了DI\Attribute\Inject类。同时检查属性的访问修饰符是否为privatePHP-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),仅供参考