【发布时间】:2011-08-13 03:35:35
【问题描述】:
假设我将代码库作为独立的 PHP 类发布。然后有人在他们的应用程序中使用该库的 1.0 版。后来,我发布了该库的 2.0 版,而同一个人出于任何原因需要在他们的应用程序中同时使用 1.0 和 2.0,因为他或我破坏了与新版本的向后兼容性。
如果类名不同,则很容易包含和实例化两者,因为没有命名冲突。但是如果类名保持不变,我们就会遇到问题:
include /lib/api-1.0/library.php;
$oldlibary = new Library();
include /lib/api-2.0/library.php;
$newlibrary = new Library();
这是行不通的,因为我们不能同时加载名称为Library 的两个类。另一位开发人员建议的另一种选择是使用命名空间。以下应该工作:
namespace old {
include /lib/api-1.0/library.php;
}
namespace new {
include /lib/api-2.0/library.php;
}
$oldlibary = new old\Library();
$newlibrary = new new\Library();
不幸的是,这不是很好的可扩展性。它适用于 2 实例情况(希望我不必首先使用),但要将其扩展到 3、4、5 或更多实例,您需要定义额外的命名空间并设置,如果你一开始就没有使用这些命名空间,那是一堆不必要的代码。
那么有没有办法动态地创建命名空间,包含一个文件,并在一个唯一命名的变量中实例化该文件中包含的类?
让我再补充一点……
我正在构建一组库,供为几个 CMS 平台构建插件/模块的其他开发人员使用。理想情况下,每个人都将始终使用我的库的最新版本,但我不能保证,也不能保证最终用户在新版本可用时总是升级他们的模块。
我正在尝试使用的用例是最终用户安装两个不同开发人员的两个不同模块:分别称为 Apple 和 Orange。这两个模块都使用我的库的 1.0 版,这很棒。我们可以实例化它一次,两组代码都可以从该功能中受益。
后来,我为这个库发布了一个小补丁。它的版本为 1.1,因为它不会破坏与 1.x 分支的向后兼容性。 Apple 的开发者立即更新他的本地版本并推送他的系统的新版本。 Orange的开发者正在休假,不打扰。
当最终用户更新 Apple 时,她会获得我的库的最新维护版本。因为它是一个维护版本,所以完全替换 1.0 版被认为是安全的。所以代码只实例化了 1.1 并且 Orange 受益于维护补丁,即使开发人员从未费心更新他们的版本。
甚至后来,出于某种原因,我决定更新我的 API 以向 Facebook 添加一些挂钩。新功能和 API 扩展对库有很大的改变,所以我将版本升级到 2.0 以将其标记为在所有情况下都可能不向后兼容。 Apple 再次介入并更新了他的代码。没有任何问题,他只是用最新版本替换了他/lib 文件夹中的我的库。 Orange 决定回到学校成为一名小丑,但已经停止维护他的模块,因此它没有得到任何更新。
当最终用户使用新版本更新 Apple 时,她会自动获得我的库的 2.0 版。但是 Orange 在他的系统中有代码已经添加了 Facebook 钩子,所以如果 2.0 默认滚入他的库中会发生冲突。因此,我没有完全替换它,而是为 Apple 实例化 2.0 一次,然后并排实例化 Orange 附带的 1.0 版本,以便它可以使用正确的代码.
这个项目的全部意义在于允许第三方开发人员基于我的代码构建系统,而不依赖于它们是否可靠,并在他们应该更新他们的代码时。对最终用户而言,什么都不会中断,并且在其他人的系统中使用我的库时更新我的库应该是一个简单的文件替换,而不是遍历和更改所有类引用。
【问题讨论】:
-
你为什么要担心这个?我了解它的用例,但看不到好处。
-
Google 开发人员的演示文稿可能会让您感兴趣youtube.com/watch?v=aAb7hSCtvGw
-
好处:不止一个开发人员可以使用我的库为特定的 CMS 平台构建模块。如果一个开发人员将他们的系统绑定到 1.0 和一个绑定到 2.0,并且最终用户尝试安装这两个模块,那么平台应该能够同时从两个版本实例化一个对象。
-
编码人员很可能会为您的第三方代码构建适配器。这样,他们可以在适配器中切换几行,以使应用程序与您的新版本库一起工作。
-
一个现实生活中这样有用的例子是两个不同的 CMS 模块,一个提供 facebook 登录,一个提供使用 facebook 的注册。两者都使用 facebook PHP SDK,但如果不能命名空间,则不能使用不同的版本。首先加载的任何版本都将优先。
标签: php namespaces dynamic-code