首页 » 网站建设 » 指定php版本运行php代码技巧_若何基于PHP 80开拓适配低版本PHP代码

指定php版本运行php代码技巧_若何基于PHP 80开拓适配低版本PHP代码

访客 2024-11-18 0

扫一扫用手机浏览

文章目录 [+]

在这种情形下,我们可能会放弃利用最新PHP代码的希望。
但是还有一个更好的选择:我们仍旧可以利用PHP8.0编写源代码,并将其转换到以前的PHP版本,乃至是PHP7.1。

在本指南中,我们将教您有关转换PHP代码的所有知识。

指定php版本运行php代码技巧_若何基于PHP 80开拓适配低版本PHP代码

什么是Transpiling?

Transpiling将源代码从编程措辞转换为相同或不同编程措辞的等效源代码。

指定php版本运行php代码技巧_若何基于PHP 80开拓适配低版本PHP代码
(图片来自网络侵删)

Transpiling并不是Web开拓中的一个新观点:客户端开拓职员很可能熟习Babel,JavaScript代码的转换器。

Babel将当代ECMAScript 2015+版本中的JavaScript代码转换为与旧浏览器兼容的旧版本。
例如,给定ES2015箭头功能:

[2, 4, 6].map((n) => n 2);

…Babel将其转换为ES5版本:

[2, 4, 6].map(function(n) { return n 2;});什么是Transpiling PHP?

Web开拓中潜在的新功能是转换做事器端代码的可能性,特殊是PHP。

转换PHP的事情办法与转换JavaScript的事情办法相同:当代PHP版本的源代码转换为旧PHP版本的等效代码。

下面是与前面相同的示例,PHP 7.4中的箭头函数:

$nums = array_map(fn($n) => $n 2, [2, 4, 6]);

…可以转换为其等效的PHP 7.3版本:

$nums = array_map( function ($n) { return $n 2; }, [2, 4, 6]);

可以转换箭头函数,由于它们是语法糖,即天生现有行为的新语法。
这是低垂的果实。

然而,也有一些新特性创建了一种新的行为,因此,对付以前版本的PHP不会有等效的代码。
PHP 8.0中引入的联合类型便是这样:

function someFunction(float|int $param): string|float|int|null{ // ...}

在这些情形下,只要开拓须要新特性,而不是生产须要新特性,就仍旧可以进行转换。
然后,我们可以大略地从转换的代码中完备删除该特性,而不会产生严重的后果。

联合类型便是这样一个例子。
此功能用于检讨输入类型与其供应的值之间是否不匹配,这有助于防止缺点。
如果与类型发生冲突,那么开拓中就会涌现缺点,我们该当在代码到达生产环境之前捕获并修复它。

因此,我们可以从生产代码中删除该功能:

function someFunction($param){ // ...}

如果缺点仍旧发生在生产中,抛出的缺点将不如利用联合类型时准确。
然而,这一潜在的缺陷被能够首先利用联合类型所抵消。

Transpiling PHP的上风

Transpiling使您能够利用最新版本的PHP编写运用程序,并天生一个在运行旧版本PHP的环境中也能事情的版本。

这对付为旧式内容管理系统(CMS)创建产品的开拓职员特殊有用。
例如,WordPress仍旧官方支持PHP5.6(只管它推举PHP7.4+)。
运行PHP版本5.6到7.2的WordPress站点的百分比为34.8%,而运行PHP版本(8.0除外)的站点的百分比高达99.5%:

WordPress利用情形统计(按版本)图像来源:WordPress

因此,面向环球受众的WordPress主题和插件很可能利用旧版本的PHP进行编码,以增加其可能的影响范围。
多亏了transpiling,这些代码可以利用PHP8.0进行编码,并且仍旧可以针对较旧的PHP版本发布,从而尽可能多地面向用户。

事实上,任何必要支持除最新版本以外的任何PHP版本(纵然在当前支持的PHP版本范围内)的运用程序都可以从中受益。

Drupal便是这样,它须要PHP7.3。
由于transpiling,开拓职员可以利用PHP8.0创建公开可用的Drupal模块,并利用PHP7.3发布它们。

另一个例子是为由于某种缘故原由而无法在其环境中运行PHP8.0的客户机创建自定义代码时。
只管如此,多亏了transpiling,开拓职员仍旧可以利用PHP8.0编写可交付成果,并在这些遗留环境中运行它们。

何时须要转换PHP(Transpile PHP)

PHP代码始终可以转换,除非它包含一些在之前的PHP版本中没有对等的PHP功能。

情形可能便是这样属性,在PHP 8.0中先容:

#[SomeAttr]function someFunc() {}#[AnotherAttr]class SomeClass {}

在前面利用箭头函数的示例中,可以转换代码,由于箭头函数是语法糖。
相反,属性创建了全新的行为。
PHP7.4及以下版本也可以复制这种行为,但只能通过手动编码,即不自动基于工具或流程(AI可以供应办理方案,但我们还没有)。

用于开拓的属性,如#[Deprecated],可以用删除联合类型的相同办法删除。
但是,不能删除在生产中修正运用程序行为的属性,也不能直接转换这些属性。

到目前为止,没有一个transpiler能够接管具有PHP8.0属性的代码并自动天生其等效PHP7.4代码。
因此,如果您的PHP代码须要利用属性,那么转换它将是困难的或不可行的。

可转换PHP功能

这些是PHP7.1及以上版本的特性,目前可以转换。
如果您的代码只利用这些特性,那么您可以确信您的转换运用程序将正常事情。
否则,您将须要评估转换的代码是否会产生故障。

PHP转换器(PHP Transpilers)

目前,有一个用于转换PHP代码的工具:Rector。

Rector是一个PHP重构工具,它根据可编程规则转换PHP代码。
我们输入源代码和要运行的规则集,Rector将转换代码。

Rector通过命令行操作,通过Composer安装在项目中。
实行时,Rector将在转换前后输出代码的“diff”(添加为绿色,删除为赤色):

来自Rector的“diff”输出

转换到哪一个PHP版本

要跨PHP版本转换代码,必须创建相应的规则。

本日,Rector库包含PHP8.0到7.1范围内的大多数代码转换规则。
因此,我们可以可靠地将PHP代码转换到7.1版。

也有从PHP7.1到7.0以及从7.0到5.6的转换规则,但这些规则并不详尽。
完成这些代码的事情正在进行中,因此我们可能终极会将PHP代码转换到5.6版。

Transpiling vs Backporting

Backporting与Transpiling类似,但更大略。
Backporting代码不一定依赖于措辞的新特性。
相反,只需重新版本的措辞复制/粘贴/改编相应的代码,就可以为旧版本的措辞供应相同的功能。

例如,PHP 8.0中引入了str_contains函数。
PHP 7.4及以下版本的相同功能可以像这样轻松实现:

if (!defined('PHP_VERSION_ID') || (defined('PHP_VERSION_ID') && PHP_VERSION_ID < 80000)) { if (!function_exists('str_contains')) { / Checks if a string contains another @param string $haystack The string to search in @param string $needle The string to search @return boolean Returns TRUE if the needle was found in haystack, FALSE otherwise. / function str_contains(string $haystack, string $needle): bool { return strpos($haystack, $needle) !== false; } }}

由于Backporting比Transpiling更大略,以是无论何时进行Backporting,我们都该当选择这种办理方案。

关于PHP8.0到7.1之间的范围,我们可以利用Symfony的polyfill库:

Polyfill PHP 7.1Polyfill PHP 7.2Polyfill PHP 7.3Polyfill PHP 7.4Polyfill PHP 8.0

这些库支持以下函数、类、常量和接口:

Transpiled PHP示例

让我们一起来看看几个转换PHP代码的示例,以及几个正在完备转换的包。

match 表达式是在PHP8.0中引入的。
此源代码:

function getFieldValue(string $fieldName): ?string{ return match($fieldName) { 'foo' => 'foofoo', 'bar' => 'barbar', 'baz' => 'bazbaz', default => null, };}

…将利用switch运算符转换到其等效的PHP 7.4版本:

function getFieldValue(string $fieldName): ?string{ switch ($fieldName) { case 'foo': return 'foofoo'; case 'bar': return 'barbar'; case 'baz': return 'bazbaz'; default: return null; }}

PHP 8.0中还引入了nullsafe操作符:

public function getValue(TypeResolverInterface $typeResolver): ?string{ return $this->getResolver($typeResolver)?->getValue();}

转换的代码须要首先将操作的值分配给新变量,以避免实行两次操作:

public function getValue(TypeResolverInterface $typeResolver): ?string{ return ($val = $this->getResolver($typeResolver)) ? $val->getValue() : null;}

PHP 8.0中还引入告终构函数属性提升功能,许可开拓职员编写更少的代码:

class QueryResolver{ function __construct(protected QueryFormatter $queryFormatter) { }}

在为PHP7.4转换时,会天生完全的代码:

class QueryResolver { protected QueryFormatter $queryFormatter; function __construct(QueryFormatter $queryFormatter) { $this->queryFormatter = $queryFormatter; }}

上面转换的代码包含PHP7.4中引入的类型化属性。
将代码向下转换到PHP7.3将其更换为docblocks:

class QueryResolver { / @var QueryFormatter / protected $queryFormatter; function __construct(QueryFormatter $queryFormatter) { $this->queryFormatter = $queryFormatter; }}PHP包

以下库正在转换以用于生产:

转换PHP的利弊

转换PHP的好处已经描述过了:它许可源代码利用PHP 8.0(即PHP的最新版本),PHP将被转换为较低版本,以便在遗留运用程序或环境中运行。

这有效地让我们成为更好的开拓职员,天生更高质量的代码。
这是由于我们的源代码可以利用PHP8.0的联合类型、PHP7.4的类型属性,以及添加到每个新版本PHP中的不同类型和伪类型(稠浊自PHP8.0,工具来自PHP7.2),以及PHP的其他当代功能。

利用这些特性,我们可以在开拓过程中更好地捕获bug,并编写更易于阅读的代码。

现在,让我们看看缺陷。

必须对它进行编码和掩护

Rector可以自动转换代码,但这个过程可能须要一些手动输入,使其与我们特定的设置合营利用。

第三方库也必须转换

每当转换它们产生缺点时,这就成为一个问题,由于我们必须深入研究它们的源代码以找出可能的缘故原由。
如果问题可以办理并且项目是开源的,我们将须要提交一个pull要求。
如果库不是开源的,我们可能会碰着障碍。

Rector不会关照我们代码何时不能转录

如果源代码包含PHP8.0属性或任何其他无法转换的功能,我们将无法连续。
但是,Rector不会检讨此条件,因此我们须要手动实行此操作。
这对付我们自己的源代码来说可能不是一个大问题,由于我们已经熟习它了,但它可能成为第三方依赖关系的障碍。

调试信息利用转换代码,而不是源代码

当运用程序在生产中天生带有堆栈跟踪的缺点时,行号将指向转换的代码。
我们须要将转换的代码转换回原始代码,以便在源代码中找到相应的行号。

还必须对已转换的代码进行预缀

我们的转桩项目和其他一些库也安装在生产环境中,可以利用相同的第三方依赖性。
此第三方依赖将转入我们的项目,并保留其其他库的原始源代码。
因此,转录的版本必须通过PHP-范围,斯特劳斯,或一些其他工具,以避免潜在的冲突。

我们的Transpile项目和其他一些也安装在生产环境中的库可以利用相同的第三方依赖关系。
这个第三方依赖项将为我们的项目转换,并为其他库保留其原始源代码。
因此,必须通过PHP Scope、Strauss或其他工具为转换版本添加前缀,以避免潜在冲突。

在连续集成 (CI) 期间必须进行转换

由于转换的代码自然会覆盖源代码,以是我们不应该在开拓打算机上运行转换过程,否则我们将冒产生副浸染的风险。
在CI运行期间运行该进程更得当(下面将对此进行详细先容)。

如何转换PHP(Transpile PHP)

首先,我们须要在开拓项目中安装Rector:

composer require rector/rector --dev

然后,我们在项目的根目录中创建一个rector.php配置文件,个中包含所需的规则集。
要将代码从PHP 8.0降级到7.1,我们利用以下配置:

use Rector\Set\ValueObject\DowngradeSetList;use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;return static function (ContainerConfigurator $containerConfigurator): void { $containerConfigurator->import(DowngradeSetList::PHP_80); $containerConfigurator->import(DowngradeSetList::PHP_74); $containerConfigurator->import(DowngradeSetList::PHP_73); $containerConfigurator->import(DowngradeSetList::PHP_72);};

为了确保流程按预期实行,我们可以在dry mode下运行Rector的process命令,通报要处理的位置(在本例中,是src/文件夹下的所有文件):

vendor/bin/rector process src --dry-run

要实行转换,我们运行Rector的process命令,该命令将修正现有位置内的文件:

vendor/bin/rector process src

请把稳:如果我们在开拓打算机中运行rector process,源代码将在src/下进行转换。
但是,我们希望在不同的位置天生转换后的代码,以便在降级代码时不会覆盖源代码。
因此,在持续集成期间运行流程最得当。

优化转换过程

要天生用于生产的转换可交付成果,只需转换用于生产的代码;可以跳过仅用于开拓的代码。
这意味着我们可以避免转换所有测试(对付我们的项目及其依赖项)和所有开拓依赖项。

关于测试,我们已经知道项目的测试在哪里了——例如,在tests/文件夹下。
我们还必须找出依赖项的位置——例如,在它们的子文件夹tests/、test/和Test/(针对不同的库)下。
然后,我们见告Rector跳过处理这些文件夹:

return static function (ContainerConfigurator $containerConfigurator): void { // ... $parameters->set(Option::SKIP, [ // Skip tests '/tests/', '/test/', '/Test/', ]);};

关于依赖关系,Composer知道哪些是用于开拓的(条眼前的须要composer.json中的 require-dev),哪些是用于生产的(条眼前的require)。

要从Composer检索生产的所有依赖项的路径,我们运行:

composer info --path --no-dev

此命令将天生包含其名称和路径的依赖项列表,如下所示:

brain/cortex /Users/leo/GitHub/leoloso/PoP/vendor/brain/cortexcomposer/installers /Users/leo/GitHub/leoloso/PoP/vendor/composer/installerscomposer/semver /Users/leo/GitHub/leoloso/PoP/vendor/composer/semverguzzlehttp/guzzle /Users/leo/GitHub/leoloso/PoP/vendor/guzzlehttp/guzzleleague/pipeline /Users/leo/GitHub/leoloso/PoP/vendor/league/pipeline

我们可以提取所有路径并将它们输入到Rector命令中,然后该命令将处理项目的src/文件夹以及包含所有生产依赖项的文件夹:

$ paths="$(composer info --path --no-dev | cut -d' ' -f2- | sed 's/ //g' | tr '\n' ' ')"$ vendor/bin/rector process src $paths

进一步的改进可以防止Rector处理那些已经利用目标PHP版本的依赖项。
如果一个库是用PHP7.1(或下面的任何版本)编写的,那么就不须要将它转换到PHP7.1。

为了实现这一点,我们可以得到须要PHP7.2及以上版本的库列表,并只处理这些库。
我们将通过Composer的why-not命令得到所有这些库的名称,如下所示:

composer why-not php "7.1." | grep -o "\S\/\S"

由于此命令不适用于--no-dev标志,为了只包含生产依赖项,我们首先须要删除开拓依赖项并重新天生自动加载程序,实行该命令,然后再次添加它们:

$ composer install --no-dev$ packages=$(composer why-not php "7.1." | grep -o "\S\/\S")$ composer install

Composer的info --path命令检索包的路径,格式如下:

# Executing this command$ composer info psr/cache --path # Produces this response:psr/cache /Users/leo/GitHub/leoloso/PoP/vendor/psr/cache

我们对列表中的所有项目实行此命令,以获取要转换的所有路径:

for package in $packagesdo path=$(composer info $package --path | cut -d' ' -f2-) paths="$paths $path"done

末了,我们将此列表供应给Rector(加上项目的src/文件夹):

vendor/bin/rector process src $paths转换代码时须要避免的坑

转换代码可以被视为一门艺术,常日须要针对项目进行调度。
让我们看看我们可能碰着的一些问题。

链式规则(Chained Rules)并不总是被处理的

链式规则是指规则须要转换前一个规则天生的代码。

例如,库symfony/cache包含以下代码:

final class CacheItem implements ItemInterface{ public function tag($tags): ItemInterface { // ... return $this; }}

从PHP 7.4转换到7.3时,函数标记必须经由两次修正:

由于规则DowngradeCovariantReturnTypeRector,返回类型 ItemInterface 必须首先转换为 self。
然后,由于规则DowngradeSelfTypeDeclarationRector,必须删除返回类型self。

终极结果该当是:

final class CacheItem implements ItemInterface{ public function tag($tags) { // ... return $this; }}

但是,Rector只输出中间阶段:

final class CacheItem implements ItemInterface{ public function tag($tags): self { // ... return $this; }}

问题是,Rector不能始终掌握规则的运用顺序。

办理方案是确定哪些链式规则未被处理,并实行新的目录运行以运用它们。

为了识别链式规则,我们在源代码上运行了两次Rector,如下所示:

$ vendor/bin/rector process src$ vendor/bin/rector process src --dry-run

第一次,我们按预期运行Rector,以实行转换。
第二次,我们利用--dry-run标志来创造是否还有须要进行的变动。
如果有,命令将退出并显示缺点代码,“diff”输出将指示仍可以运用哪些规则。
这意味着第一次运行未完成,某些链式规则未被处理。

利用–dry-run flag运行Rector

一旦我们确定了未运用的链式规则,我们就可以创建另一个目录配置文件——例如,rector-chained-rule.php 将实行短缺的规则。
这一次,我们不须要为 src/下的所有文件处理一整套规则,而是可以在须要运用该规则的特定文件上运行特定的缺失落规则:

// rector-chained-rule.phpuse Rector\Core\Configuration\Option;use Rector\DowngradePhp74\Rector\ClassMethod\DowngradeSelfTypeDeclarationRector;use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); $services->set(DowngradeSelfTypeDeclarationRector::class); $parameters = $containerConfigurator->parameters(); $parameters->set(Option::PATHS, [ __DIR__ . '/vendor/symfony/cache/CacheItem.php', ]);};

末了,我们在第二次通报时通过输入--config见告Rector利用新的配置文件:

# First pass with all modifications$ vendor/bin/rector process src# Second pass to fix a specific problem$ vendor/bin/rector process --config=rector-chained-rule.phpComposer依赖性可能不一致

库可以声明一个依赖项进行开拓(即在composer.json中的require-dev 下),但仍旧可以引用个中的一些代码进行生产(例如在 src/下的一些文件上,而不是在 tests/ 下)。

常日,这不是问题,由于该代码可能不会加载莅临盆环境中,因此运用程序上永久不会涌现缺点。
但是,当Rector处理源代码及其依赖项时,它会验证是否可以加载所有引用的代码。
如果任何文件引用了未安装库中的某段代码(由于它被声明为仅用于开拓),Rector将抛出一个缺点。

例如,Symfony缓存组件中的类 EarlyExpirationHandler 实现Messenger组件中的接口 MessageHandlerInterface :

class EarlyExpirationHandler implements MessageHandlerInterface{ //...}

但是,symfony/cache声明 symfony/messenger是开拓的依赖项。
然后,在依赖symfony/cache的项目上运行Rector时,它将抛出一个缺点:

[ERROR] Could not process "vendor/symfony/cache/Messenger/EarlyExpirationHandler.php" file, due to: "Analyze error: "Class Symfony\Component\Messenger\Handler\MessageHandlerInterface not found.". Include your files in "$parameters->set(Option::AUTOLOAD_PATHS, [...]);" in "rector.php" config. See https://github.com/rectorphp/rector#configuration".

这个问题有三种办理办法:

1.在Rector配置中,跳过处理引用该代码段的文件:

return static function (ContainerConfigurator $containerConfigurator): void { // ... $parameters->set(Option::SKIP, [ __DIR__ . '/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php', ]);};

2.下载短缺的库并添加其路径,以便由Rector自动加载:

return static function (ContainerConfigurator $containerConfigurator): void { // ... $parameters->set(Option::AUTOLOAD_PATHS, [ __DIR__ . '/vendor/symfony/messenger', ]);};

3.让您的项目依赖于短缺的库进行生产:

composer require symfony/messenger转换和连续集成

如前所述,在我们的开拓打算机中,在运行Rector时必须利用 --dry-run 标志,否则,源代码将被转换的代码覆盖。
因此,更适宜在持续集成(CI)期间运行实际的转换过程,我们可以启动临时运行程序来实行该过程。

实行转换过程的空想韶光是为我们的项目天生发布时。
例如,下面的代码是GitHub Actions的事情流,它创建了WordPress插件的发布:

name: Generate Installable Plugin and Upload as Release Asseton: release: types: [published]jobs: build: name: Build, Downgrade and Upload Release runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Downgrade code for production (to PHP 7.1) run: | composer install vendor/bin/rector process sed -i 's/Requires PHP: 7.4/Requires PHP: 7.1/' graphql-api.php - name: Build project for production run: | composer install --no-dev --optimize-autoloader mkdir build - name: Create artifact uses: montudor/action-zip@v0.1.0 with: args: zip -X -r build/graphql-api.zip . -x .git node_modules/\ . "/\." CODE_OF_CONDUCT.md CONTRIBUTING.md ISSUE_TEMPLATE.md PULL_REQUEST_TEMPLATE.md rector.php .dist composer. dev-helpers build - name: Upload artifact uses: actions/upload-artifact@v2 with: name: graphql-api path: build/graphql-api.zip - name: Upload to release uses: JasonEtco/upload-to-release@master with: args: build/graphql-api.zip application/zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

此事情流包含通过GitHub操作发布WordPress插件的标准过程。
新添加的将插件代码从PHP7.4转换到7.1的步骤如下:

- name: Downgrade code for production (to PHP 7.1) run: | vendor/bin/rector process sed -i 's/Requires PHP: 7.4/Requires PHP: 7.1/' graphql-api.php

综上所述,此事情流现在实行以下步骤:

从WordPress插件的存储库中检讨WordPress插件的源代码,该插件是用PHP7.4编写的安装其Composer依赖项将其代码从PHP7.4转换到7.1将插件主文件头中的“Requires PHP”条款从“7.4”修正为“7.1”删除开拓所需的依赖项创建插件的.zip文件,打消所有不须要的文件将.zip文件作为发布资产上载(此外,还作为GitHub操作的工件上载)测试转换代码

一旦代码被转换到 PHP 7.1,我们怎么知道它事情得很好?或者,换句话说,我们怎么知道它已经被彻底转换,并且没有留下更高版本的 PHP 代码的残余?

与转存代码类似,我们可以在 CI 流程中实现办理方案。
这个想法是设置与PHP 7.1的亚军的环境,并在转桩代码上运行一个衬垫。
如果任何代码与 PHP 7.1 不兼容(例如未转换的 PHP 7.4 中的键入属性),则衬里会抛出错误。

Php 的衬里效果很好PHP 平行林特.我们可以将此库安装为项目开拓的依赖项,或者让 CI 过程将其安装为独立的作曲家项目:

一旦代码被转换到PHP7.1,我们如何知道它事情良好?或者,换句话说,我们如何知道它已经被彻底转换,并且没有留下更高版本的PHP代码的残余?

与转换代码类似,我们可以在CI流程中实现办理方案。
其想法是利用PHP7.1设置运行者环境,并在转换的代码上运行linter。
如果任何代码与PHP7.1不兼容(例如PHP7.4中未转换的类型化属性),那么linter将抛出一个缺点。

PHP的一个运行良好的linter是PHP并行Lint。
我们可以将此库作为开拓依赖项安装在我们的项目中,或者让CI流程将其作为独立的Composer项目安装:

composer create-project php-parallel-lint/php-parallel-lint

每当代码包含PHP 7.2及更高版本时,PHP Parallel Lint将抛出如下缺点:

Run php-parallel-lint/parallel-lint layers/ vendor/ --exclude vendor/symfony/polyfill-ctype/bootstrap80.php --exclude vendor/symfony/polyfill-intl-grapheme/bootstrap80.php --exclude vendor/symfony/polyfill-intl-idn/bootstrap80.php --exclude vendor/symfony/polyfill-intl-normalizer/bootstrap80.php --exclude vendor/symfony/polyfill-mbstring/bootstrap80.phpPHP 7.1.33 | 10 parallel jobs............................................................ 60/2870 (2 %)............................................................ 120/2870 (4 %)............................................................... 660/2870 (22 %).............X.............................................. 720/2870 (25 %)............................................................ 780/2870 (27 %)............................................................... 2820/2870 (98 %).................................................. 2870/2870 (100 %)Checked 2870 files in 15.4 secondsSyntax error found in 1 file------------------------------------------------------------Parse error: layers/GraphQLAPIForWP/plugins/graphql-api-for-wp/graphql-api.php:5553| '0.8.0',54| \__('GraphQL API for WordPress', 'graphql-api'),> 55| ))) {56| $plugin->setup();57| }Unexpected ')' in layers/GraphQLAPIForWP/plugins/graphql-api-for-wp/graphql-api.php on line 55Error: Process completed with exit code 1.

让我们将绒毛添加到我们的 CI 事情流中。
实行将代码从 PHP 8.0 转换到 7.1 并测试它的步骤是:

查看源代码让环境运行 PHP 8.0,以便校长可以阐明源代码将代码转换到 PHP 7.1安装 PHP 绒毛工具将环境的 PHP 版本切换到 7.1在转存代码上运行衬垫

这GitHub 行动事情流程做这项事情:

让我们将linter添加到CI的事情流中。
将代码从PHP 8.0转换到7.1并进行测试的步骤如下:

查看源代码让环境运行PHP8.0,这样校长就可以阐明源代码了将代码转换到PHP7.1安装PHP linter工具将环境的PHP版本切换到7.1在转换的代码上运行linter

此GitHub操作事情流实行以下任务:

name: Downgrade PHP testsjobs: main: name: Downgrade code to PHP 7.1 via Rector, and execute tests runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set-up PHP uses: shivammathur/setup-php@v2 with: php-version: 8.0 coverage: none - name: Local packages - Downgrade PHP code via Rector run: | composer install vendor/bin/rector process # Prepare for testing on PHP 7.1 - name: Install PHP Parallel Lint run: composer create-project php-parallel-lint/php-parallel-lint --ansi - name: Switch to PHP 7.1 uses: shivammathur/setup-php@v2 with: php-version: 7.1 coverage: none # Lint the transpiled code - name: Run PHP Parallel Lint on PHP 7.1 run: php-parallel-lint/parallel-lint src/ vendor/ --exclude vendor/symfony/polyfill-ctype/bootstrap80.php --exclude vendor/symfony/polyfill-intl-grapheme/bootstrap80.php --exclude vendor/symfony/polyfill-intl-idn/bootstrap80.php --exclude vendor/symfony/polyfill-intl-normalizer/bootstrap80.php --exclude vendor/symfony/polyfill-mbstring/bootstrap80.php

请把稳,必须从linter中打消Symfony的polyfill库中的几个 bootstrap80.php 文件(不须要转换)。
这些文件包含PHP8.0,因此linter在处理它们时会抛出错误。
但是,打消这些文件是安全的,由于只有在运行PHP 8.0或更高版本时,才会在生产环境中加载这些文件:

if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php';}小结

本文教我们如何转换PHP代码,许可我们在源代码中利用PHP8.0,并创建一个适用于PHP7.1的发行版。
Transpiling是通过Rector(一种PHP重构工具)完成的。

转换代码使开拓职员的功效效率更高,由于我们可以更好地捕获开拓中的缺点,并天生自然更易于阅读和理解的代码。

Transpiling还使我们能够将具有特定PHP需求的代码与CMS分离。
如果我们希望利用最新版本的PHP来创建公开可用的WordPress插件或Drupal模块,而不严重限定我们的用户群,那么我们现在可以这样做。

文章引自“跨版本PHP代码转换终极教程 - 闪电博 (wbolt.com)

https://www.wbolt.com/transpiling-php.html

翻译可能有偏差,请把稳甄别!

标签:

相关文章