我使用PHP 8.0readonly
关键字编写了一个PHP库,然后我意识到它将很好地支持早期版本的PHP,如7.4。
我可以很容易地从我的代码中删除readonly
关键字,但我不想这样做——他们放在那里是有原因的!
有C背景,我马上想到了宏,但PHP似乎没有。我已经在谷歌上搜索了这个答案,以便在PHP中添加类似宏的行为,但它看起来像是多余的。这只是一个文件,而我的库目前有26个文件。
是否有一个简单的方法使PHP 7.4只是忽略readonly
关键字,使我的代码跨版本?这段C代码有什么影响吗?
#if PHP_VERSION < 8
#define readonly /**/
#enif
也许一些composer
构建选项,可以在打包之前预处理文件?
开箱即用,PHP不包含您所希望的类型的条件编译。
一种选择是使用自定义的自动加载器或Composer钩子动态地预处理源文件。我们的想法是让正常的代码运行到要include
文件的地方,然后获取其内容并对其进行操作。
/* IF PHP 8 */ readonly /* END IF */
,并将它们与一个简单的正则表达式模式匹配:
$php_code = file_get_contents($php_file_being_loaded);
if ( PHP_VERSION_ID < 80000 ) {
$php_code = preg_replace('#/* IF PHP 8 */.*?/* END IF */#s', '', $php_code);
}
eval($php_code);
或者,您可以"离线"运行预处理,以自动生成库的并行版本:一个用于PHP 8.0及以上版本,另一个用于PHP 7.4。同样,这可以像上面一样简单,或者您可以使用像Rector这样的工具,它可以根据设置的规则(包括"降级")解析和重写普通的PHP代码(没有额外的标记)。
PHP没有被编译,因此没有编译器宏。
根据向后不兼容的变化,它是一个新的关键字:
readonly
现在是一个关键字。但是,它仍然可以用作函数名。
所以你有两个选择:a)不重新赋值或者b)保持两个版本。
大多数框架只是因为这个原因而避免使用现代功能(WordPress, Symfony, Laravel),但如果你坚持,你最好的选择可能是Composer,你可以有一个v1.x。X with composer.json
{
"require": {
"php": ">=7.4"
},
}
和一个v2.x。X with composer.json
{
"require": {
"php": ">=8.0"
},
}
然后当人们执行composer require lib
时,composer会自动扫描并安装与本地php版本和composer兼容的库的最新版本。json-constraints (-:
缺点是,只要您打算支持PHP 7.4,您就必须同时维护库的v1和v2 .
另一种选择是使用lib.php
if(PHP_MAJOR_VERSION >= 8){
require("lib_modern.php");
} else{
require("lib_legacy.php");
}
的缺点是必须同时维护lib_modern和lib_legacy