我知道依赖注入模式,它似乎是可用于处理需要其他类的实例正常运行的类的最佳解决方案。但是当涉及到处理某个类存在的场景时,但是在错误的版本中, DI 或任何其他OOP模式显然根本没有帮助。
在PHP中处理基于版本的库依赖项的好方法是什么?
这是一种说明我的意思的方式(伪代码):
class payment_module_base {
var $baseVersion;
function __construct() {
$this->baseversion = 12; //Version 12
}
// Other relevant methods...
}
class card_payments extend payment_module_base {
function construct() {
if ($this->baseversion <= 10)
Throw New Exception("Card payments isnt working with base module V. <10");
}
}
注意:这是出于说明的目的 - 我知道这应该被提升到特定的测试,以免产生关于版本的条件的生产代码,除非真的有必要。
答案 0 :(得分:3)
我只是不在PHP中处理它,而是在服务器,DI配置或我的自动加载器中处理它。当我需要使用同一个库的多个不同版本时,我通常会设置我的目录结构:
/usr/share/php/SomeLibrary-1.0
/usr/Share/php/SomeLibrary-2.0
/usr/share/php/SomeLibrary --> SomeLibrary-2.0
每个版本都放在一个单独的版本化文件夹中。有一个无版本的符号链接指向最新版本。
在我的DI容器中(我经常使用symfony组件中的那个)我只是将其配置为从正确的路径加载文件。或者,您可以设置自动加载器,以便加载正确的版本。
简而言之,要使用的库版本(以及最终的库路径)是应用程序配置的一部分,而不是应用程序代码。
<强>更新强>
当一个库需要另一个库的特定版本并且它只能找到不正确的版本时,我只是抛出异常并让应用程序处理它(通常这意味着显示错误并退出)。我不会尝试加载特定版本的库。我为sfServiceContainer(我选择的依赖注入解决方案)加载配置文件中配置的任何内容。如果这是错误的版本,则管理员必须更新配置设置。
不要尝试自动搜索不同的库版本,尝试加载正确的版本。只需要一个人工配置应该从哪个路径加载哪个库(并提供具有理智默认值的配置)。
答案 1 :(得分:1)
很多人都对库文件顶部的定义发誓。它很简单,性能也很好......也许太简单了。
// -- At the top of the library, we define this ...
define('PAYMENT_LIBRARY_VER', 324);
// -- At some point in the code, we check it!
if( defined('PAYMENT_LIBRARY_VER') && PAYMENT_LIBRARY_VER <= 320 )
throw new HissyFit("This is just an alias for an exception.");
我认为自己有点笨拙,并且更喜欢工厂版本管理......
// -- In a file far far away ...
class PaymentProcessor_r324 extends PaymentProcessor
{
...
}
// -- Somewhere else ...
class PaymentProcessor_r325 extends PaymentProcessor
{
...
}
// -- In the main library class "holder"
class PaymentProcessorManager
{
/**
* The latest version of the library
*/
const LATEST_VERSION = 324;
/**
* Initialise a new instance of the PaymentProcessor.
* @param $ver
* @return PaymentProcessor
*/
public static function Initialise( $revision = null )
{
if( $revision === null )
$revision = self::LATEST_VERSION;
var $c = "PaymentProcessor_r{$revision}";
return new $c();
}
}
// -- Pretty much anywhere you like, and autoloading friendly to boot.
if( PaymentProcessorManager::LATEST_VERSION < 300 )
throw new HissyFit("This is just an alias for an exception.");
此模型更具可扩展性。您必须引用该类才能获取最新版本,但不需要它的实例。引用意味着您拥有的任何自动加载代码都有机会获取该类,您可以在管道中的任何位置运行版本检查。同时,您可以选择支持该类的多个版本,并轻松加载开发版本。
// -- Even though the 'latest version' is 324, there's nothing to stop me
// from loading my development version, #325.
var $paymentProcessor = PaymentProcessorManager::Initialise(325);
此模型还支持构建依赖项标头...
if( PaymentProcessorManager::LATEST_VERSION < 300
|| OtherModuleManager::LATEST_VERSION < 240 )
throw new HissyFit("The minimum requirements for this functionality are not met.");
我会说作为启动说明虽然PHP似乎不适合这种安排...它非常松散,需要大量的手动检查才能确保全局兼容性。如果有合理的可能,我会避免在PHP的精彩世界中进行版本控制。
更新:哦,是的,我差点忘了。您可能希望沿着以下行的类别名不需要可怕的版本特定链。
class_alias('PaymentProcessor_r' . PaymentProcessorManager::LATEST_VERSION, 'PaymentProcessorLatest');