Wordpress

Pandhuan Ultimate kanggo Transpiling Kode PHP

Ing kahanan becik, kita kudu nggunakake PHP 8.0 (versi paling anyar nalika nulis iki) kanggo kabeh situs kita lan nganyari sanalika versi anyar dirilis. Nanging, pangembang asring kudu nggarap versi PHP sadurunge, kayata nalika nggawe plugin umum kanggo WordPress utawa nggarap kode warisan sing ngalangi nganyarke lingkungan server web.

Ing kahanan kasebut, kita bisa ngilangi pangarep-arep kanggo nggunakake kode PHP paling anyar. Nanging ana alternatif sing luwih apik: kita isih bisa nulis kode sumber nganggo PHP 8.0 lan transpile menyang versi PHP sadurunge - malah menyang PHP 7.1.

Ing pandhuan iki, kita bakal mulang sampeyan kabeh sing sampeyan kudu ngerti babagan transpiling kode PHP.

Apa Transpiling?

Transpiling ngowahi kode sumber saka basa pamrograman dadi kode sumber sing padha karo basa pamrograman sing padha utawa beda.

Transpiling dudu konsep anyar ing pangembangan web: pangembang sisih klien mesthine bakal kenal karo Babel, transpiler kanggo kode JavaScript.

Babel ngowahi kode JavaScript saka versi ECMAScript 2015+ modern dadi versi warisan sing kompatibel karo browser lawas. Contone, diwenehi fungsi panah ES2015:

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

...Babel bakal ngowahi dadi versi ES5:

[2, 4, 6].map(function(n) {
  return n * 2;
});

Apa Transpiling PHP?

Sing potensial anyar ing pangembangan web yaiku kemungkinan transpiling kode sisih server, utamane PHP.

Transpiling PHP dianggo kanthi cara sing padha karo transpiling JavaScript: kode sumber saka versi PHP modern diowahi dadi kode sing padha kanggo versi PHP lawas.

Sawise conto sing padha kaya sadurunge, fungsi panah saka PHP 7.4:

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

... bisa ditranspile menyang versi PHP 7.3 sing padha:

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

Fungsi panah bisa ditranspil amarga minangka gula sintaksis, yaiku sintaksis anyar kanggo ngasilake prilaku sing wis ana. Iki minangka woh-wohan sing sithik.

Nanging, ana uga fitur-fitur anyar sing nggawe prilaku anyar, lan kaya mangkono, ora bakal ana kode sing padha kanggo versi PHP sadurunge. Semono uga jinis serikat pekerja, sing dikenalake ing PHP 8.0:

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

Ing kahanan kasebut, transpiling isih bisa ditindakake anggere fitur anyar dibutuhake kanggo pangembangan nanging ora kanggo produksi. Banjur, kita bisa mbusak kabeh fitur saka kode transpiled tanpa jalaran serius.

Salah sawijining conto yaiku jinis serikat pekerja. Fitur iki digunakake kanggo mriksa manawa ora ana kecocokan antarane jinis input lan nilai sing diwenehake, sing mbantu nyegah kewan omo. Yen ana konflik karo jinis, bakal ana kesalahan sing wis dikembangake, lan kita kudu nyekel lan ndandani sadurunge kode kasebut tekan produksi.

Mula, kita bisa mbusak fitur kasebut saka kode produksi:

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

Yen kesalahan isih kedadeyan ing produksi, pesen kesalahan sing dibuwang bakal kurang tepat tinimbang yen kita duwe jinis serikat pekerja. Nanging, kerugian potensial iki luwih gedhe tinimbang bisa nggunakake jinis serikat ing wiwitan.

Ing donya sing sampurna, kita kudu bisa nggunakake PHP 8.0 ing kabeh situs kita lan nganyari sanalika versi anyar dirilis 😌 Nanging ora mesthi kedadeyan kasebut. Sinau kabeh sing sampeyan kudu ngerti babagan transpiling kode PHP ing kene 👇Klik kanggo Tweet

Kaluwihan Transpiling Kode PHP

Transpiling mbisakake siji kanggo kode aplikasi nggunakake versi paling anyar saka PHP lan gawé release sing uga bisa digunakake ing lingkungan sing nganggo versi lawas saka PHP.

Iki bisa migunani utamane kanggo pangembang sing nggawe produk kanggo sistem manajemen konten (CMS) warisan. WordPress, umpamane, isih resmi ndhukung PHP 5.6 (sanajan nyaranake PHP 7.4+). Persentase situs WordPress sing nganggo PHP versi 5.6 nganti 7.2 — sing kabeh End-of-Life (EOL), tegese padha ora nampa nganyari keamanan maneh — udakara 34.8%, lan sing mlaku ing versi PHP liyane kajaba 8.0 kanthi 99.5%:

Panggunaan WordPress miturut versi
Statistik panggunaan WordPress miturut versi. Sumber gambar: WordPress

Akibate, tema lan plugin WordPress sing ditargetake kanggo pamirsa global bakal kemungkinan bakal dikode karo versi PHP lawas kanggo nambah jangkauan sing bisa ditindakake. Thanks kanggo transpiling, iki bisa dikode nggunakake PHP 8.0, lan isih dirilis kanggo versi PHP sing luwih lawas, saengga bisa nargetake pangguna sabisa.

Pancen, aplikasi apa wae sing kudu ndhukung versi PHP liyane kajaba sing paling anyar (sanajan ing jangkoan versi PHP sing didhukung saiki) bisa entuk manfaat.

Iki minangka kasus Drupal, sing mbutuhake PHP 7.3. Thanks kanggo transpiling, pangembang bisa nggawe modul Drupal sing kasedhiya kanggo umum nggunakake PHP 8.0, lan ngeculake nganggo PHP 7.3.

Conto liyane yaiku nalika nggawe kode khusus kanggo klien sing ora bisa mbukak PHP 8.0 ing lingkungane amarga siji alasan utawa liyane. Nanging, amarga transpiling, pangembang isih bisa menehi kode kiriman nggunakake PHP 8.0 lan mbukak ing lingkungan warisan kasebut.

Nalika Transpile PHP

Kode PHP bisa tansah transpiled kajaba ngemot sawetara fitur PHP sing ora padha karo versi PHP sadurungé.

Sing bisa uga kedadeyan karo atribut, sing dikenalake ing PHP 8.0:

#[SomeAttr]
function someFunc() {}

#[AnotherAttr]
class SomeClass {}

Ing conto sadurunge nggunakake fungsi panah, kode bisa transpiled amarga fungsi panah gula sintaksis. Atribut, ing kontras, nggawe prilaku sing anyar. Prilaku iki uga bisa direproduksi nganggo PHP 7.4 lan ngisor, nanging mung kanthi manual coding, yaiku ora kanthi otomatis adhedhasar alat utawa proses (AI bisa menehi solusi, nanging kita durung ana).

Atribut dimaksudaké kanggo nggunakake pembangunan, kayata #[Deprecated], bisa dibusak kanthi cara sing padha mbusak jinis serikat pekerja. Nanging atribut sing ngowahi prilaku aplikasi ing produksi ora bisa dibusak, lan uga ora bisa langsung transpiled.

Nganti saiki, ora ana transpiler sing bisa njupuk kode nganggo atribut PHP 8.0 lan kanthi otomatis ngasilake kode PHP 7.4 sing padha. Akibate, yen kode PHP sampeyan kudu nggunakake atribut, banjur transpiling bakal angel utawa ora bisa ditindakake.

Fitur PHP sing Bisa Dipindhah

Iki minangka fitur saka PHP 7.1 lan ndhuwur sing saiki bisa ditransfer. Yen kode sampeyan mung nggunakake fitur-fitur kasebut, sampeyan bisa ngrasakake kepastian yen aplikasi transpiled sampeyan bakal bisa digunakake. Yen ora, sampeyan kudu netepake yen kode transpiled bakal gagal.

Versi PHP fitur
7.1 kabeh
7.2 - object jinis
- jinis parameter widening
- PREG_UNMATCHED_AS_NULL gendera ing preg_match
7.3 - Tugas referensi ing list() / destructuring array (Kajaba ing njero foreach — #4376)
- Sintaks Heredoc lan Nowdoc sing fleksibel
– Trailing koma ing fungsi telpon
- set(raw)cookie nampa $opsi argumen
7.4 - Properti sing diketik
- Fungsi panah
– Operator penugasan null coalescing
– Unpacking nang array
- Pemisah literal angka
- strip_tags() karo array saka jeneng tag
– jinis bali kovarian lan jinis param kontravarian
8.0 - Tipe Uni
- mixed jinis pseudo
- static jinis bali
- ::class konstanta sihir ing obyek
- match ungkapan
- catch pangecualian mung miturut jinis
- Operator null-aman
- Promosi properti konstruktor kelas
- Ngilangi koma ing dhaptar parameter lan penutupan use dhaptar

PHP Transpilers

Saiki, ana siji alat kanggo transpiling kode PHP: Rektor.

Rektor minangka alat rekonstruktor PHP, sing ngowahi kode PHP adhedhasar aturan sing bisa diprogram. We input kode sumber lan pesawat saka aturan kanggo mbukak, lan Rektor bakal ngowahi kode.

Rektor dilakokno liwat baris printah, diinstal ing project liwat Composer. Nalika dieksekusi, Rektor bakal ngasilake "beda" (tambahan ing ijo, mbusak abang) kode sadurunge lan sawise konversi:

"beda" output saka Rektor
"beda" output saka Rektor

Versi PHP kanggo Transpile menyang

Kanggo transpile kode ing versi PHP, aturan sing cocog kudu digawe.

Dina iki, perpustakaan Rektor kalebu akeh aturan kanggo transpiling kode ing sawetara PHP 8.0 kanggo 7.1. Mula, kita bisa andal transpile kode PHP nganti versi 7.1.

Ana uga aturan kanggo transpiling saka PHP 7.1 kanggo 7.0 lan saka 7.0 kanggo 5.6, nanging iki ora exhaustive. Pakaryan lagi ditindakake kanggo ngrampungake, saengga pungkasane bisa ngowahi kode PHP menyang versi 5.6.

Transpiling vs Backporting

Backporting padha karo transpiling, nanging luwih prasaja. Kode backporting ora kudu gumantung ing fitur anyar saka basa. Nanging, fungsi sing padha bisa kasedhiya kanggo versi lawas saka basa mung kanthi nyalin / nempel / adaptasi kode sing cocog saka versi anyar saka basa.

Contone, fungsi str_contains dikenalaké ing PHP 8.0. Fungsi sing padha kanggo PHP 7.4 lan ing ngisor iki bisa ditindakake kanthi gampang kaya iki:

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;
    }
  }
}

Amarga backporting luwih gampang tinimbang transpiling, kita kudu milih solusi iki nalika backporting nindakake tugas kasebut.

Babagan kisaran antarane PHP 8.0 nganti 7.1, kita bisa nggunakake perpustakaan polyfill Symfony:

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

Pustaka iki ndhukung fungsi, kelas, konstanta, lan antarmuka ing ngisor iki:

Versi PHP fitur
7.2 fungsi:

  • spl_object_id
  • utf8_encode
  • utf8_decode

konstanta:

  • PHP_FLOAT_*
  • PHP_OS_FAMILY
7.3 fungsi:

  • array_key_first
  • array_key_last
  • hrtime
  • is_countable

Pangecualian:

  • JsonException
7.4 fungsi:

  • get_mangled_object_vars
  • mb_str_split
  • password_algos
8.0 Interfaces:

  • Stringable

Kelas:

  • ValueError
  • UnhandledMatchError

konstanta:

  • FILTER_VALIDATE_BOOL

fungsi:

  • fdiv
  • get_debug_type
  • preg_last_error_msg
  • str_contains
  • str_starts_with
  • str_ends_with
  • get_resource_id

Tuladha PHP Transpiled

Ayo dipriksa sawetara conto kode PHP sing ditranspil, lan sawetara paket sing lagi ditranspile kanthi lengkap.

Kode PHP

The match expression iki ngenalaken ing PHP 8.0. Kode sumber iki:

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

...bakal ditransfer menyang versi PHP 7.4 sing padha, nggunakake switch operator:

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

Operator nullsafe uga dikenalake ing PHP 8.0:

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

Kode transpiled kudu nemtokake nilai operasi menyang variabel anyar, supaya ora nglakokake operasi kaping pindho:

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

Fitur promosi properti konstruktor, uga dikenalake ing PHP 8.0, ngidini pangembang nulis kode kurang:

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

Nalika transpiling kanggo PHP 7.4, potongan lengkap kode diprodhuksi:

 class QueryResolver
 {
  protected QueryFormatter $queryFormatter;

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

Kode transpil ing ndhuwur ngemot properti sing diketik, sing dikenalake ing PHP 7.4. Transpiling kode kasebut menyang PHP 7.3 ngganti karo docblocks:

 class QueryResolver
 {
  /**
   * @var QueryFormatter
   */
  protected $queryFormatter;

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

Paket PHP

Pustaka ing ngisor iki ditranspilasi kanggo produksi:

Pustaka / katrangan Kode / cathetan
Rektor
Alat rekonstruktor PHP sing ndadekake transpiling bisa
- Kode sumber
- Kode transpil
– Cathetan
Standar Coding Gampang
Alat supaya kode PHP manut sakumpulan aturan
- Kode sumber
- Kode transpil
– Cathetan
GraphQL API kanggo WordPress
Plugin nyedhiyakake server GraphQL kanggo WordPress
- Kode sumber
- Kode transpil
– Cathetan

Pros lan Cons saka Transpiling PHP

Keuntungan saka transpiling PHP wis diterangake: ngidini kode sumber nggunakake PHP 8.0 (yaiku versi PHP paling anyar), sing bakal diowahi dadi versi sing luwih murah kanggo PHP supaya produksi bisa mlaku ing aplikasi utawa lingkungan warisan.

Iki kanthi efektif ngidini kita dadi pangembang sing luwih apik, ngasilake kode kanthi kualitas sing luwih dhuwur. Iki amarga kode sumber kita bisa nggunakake jinis union PHP 8.0, properti sing diketik PHP 7.4, lan macem-macem jinis lan jinis pseudo sing ditambahake ing saben versi PHP anyar (mixed saka PHP 8.0, object saka PHP 7.2), ing antarane fitur modern PHP liyane.

Nggunakake fitur-fitur kasebut, kita bisa luwih apik nyekel bug sajrone pangembangan lan nulis kode sing luwih gampang diwaca.

Saiki, ayo goleki kekurangane.

Kudu Dikode lan Dijaga

Rektor bisa transpile kode kanthi otomatis, nanging proses kasebut bakal mbutuhake sawetara input manual supaya bisa digunakake karo persiyapan khusus kita.

Pustaka Pihak Katelu Uga Kudu Dipindhah

Iki dadi masalah nalika transpiling ngasilake kesalahan amarga kita kudu nyelidiki kode sumber kasebut kanggo ngerteni sebabe. Yen masalah bisa didandani lan proyek kasebut mbukak sumber, kita kudu ngirim panjaluk tarik. Yen perpustakaan ora mbukak sumber, kita bisa kenek roadblock.

Rektor ora ngandhani yen kode kasebut ora bisa ditransfer

Yen kode sumber ngandhut PHP 8.0 atribut utawa fitur liyane sing ora bisa transpiled, kita ora bisa nerusake. Nanging, Rektor ora bakal mriksa kahanan kasebut, mula kudu ditindakake kanthi manual. Iki bisa uga ora dadi masalah gedhe babagan kode sumber kita amarga kita wis ngerti, nanging bisa dadi alangan babagan dependensi pihak katelu.

Informasi Debugging Nggunakake Kode Transpiled, Ora Kode Sumber

Nalika aplikasi ngasilake pesen kesalahan kanthi tilak tumpukan ing produksi, nomer baris bakal nuding kode transpiled. Kita kudu ngowahi maneh saka transpiled menyang kode asli kanggo nemokake nomer baris sing cocog ing kode sumber.

Kode Transpiled Uga Kudu Ater-ater

Proyek transpiled lan sawetara perpustakaan liyane sing uga diinstal ing lingkungan produksi bisa nggunakake ketergantungan pihak katelu sing padha. Ketergantungan pihak katelu iki bakal ditranspile kanggo proyek kita lan tetep kode sumber asli kanggo perpustakaan liyane. Mula, versi transpil kudu diaterake liwat PHP-Scoper, Strauss, utawa alat liyane kanggo ngindhari konflik potensial.

Transpiling kudu ditindakake sajrone Integrasi Terus (CI)

Amarga kode transpil kanthi alami bakal ngilangi kode sumber, kita ora kudu mbukak proses transpiling ing komputer pangembangan kita, utawa kita bakal duwe risiko nggawe efek samping. Mlaku proses sak CI run luwih cocok (liyane ing ngisor iki).

Carane Transpile PHP

Pisanan, kita kudu nginstal Rektor ing proyek kita kanggo pangembangan:

composer require rector/rector --dev

Kita banjur nggawe a rector.php file konfigurasi ing direktori ROOT saka project ngemot set aturan sing dibutuhake. Kanggo downgrade kode saka PHP 8.0 kanggo 7.1, kita nggunakake konfigurasi iki:

use RectorSetValueObjectDowngradeSetList;
use SymfonyComponentDependencyInjectionLoaderConfiguratorContainerConfigurator;

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);
};

Kanggo mesthekake yen proses kasebut bisa ditindakake kaya sing dikarepake, kita bisa mbukak Rektor process printah ing mode garing, maringaken lokasi (s) kanggo proses (ing kasus iki, kabeh file ing folder src/):

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

Kanggo nindakake transpiling, kita mbukak Rektor process printah, sing bakal ngowahi file ing lokasi sing wis ana:

vendor/bin/rector process src

Wigati: yen kita mlaku rector process ing komputer pembangunan kita, kode sumber bakal diowahi ing panggonan, ing src/. Nanging, kita pengin ngasilake kode sing diowahi ing lokasi sing beda supaya ora ngilangi kode sumber nalika mudhun kode. Mulane, mlaku proses paling cocok sajrone integrasi terus-terusan.

Ngoptimalake Proses Transpiling

Kanggo ngasilake pangiriman transpiled kanggo produksi, mung kode kanggo produksi sing kudu diowahi; kode mung perlu kanggo pembangunan bisa dilewati. Tegese kita bisa ngindhari transpiling kabeh tes (kanggo proyek lan dependensi) lan kabeh dependensi kanggo pembangunan.

Babagan tes, kita bakal ngerti ing ngendi lokasi proyek kita - umpamane, ing folder kasebut tests/. Kita uga kudu ngerteni endi sing kanggo dependensi - contone, ing subfolder tests/, test/ lan Test/ (kanggo perpustakaan beda). Banjur, kita ngandhani Rektor supaya ora ngolah folder kasebut:

return static function (ContainerConfigurator $containerConfigurator): void {
  // ...

  $parameters->set(Option::SKIP, [
    // Skip tests
    '*/tests/*',
    '*/test/*',
    '*/Test/*',
  ]);
};

Babagan dependensi, Komposer ngerti endi sing bakal dikembangake (sing ana ing entri require-dev in composer.json) lan sing kanggo produksi (sing ana ing entri require).

Kanggo njupuk saka Composer path kabeh dependensi kanggo produksi, kita mbukak:

composer info --path --no-dev

Printah iki bakal ngasilake dhaptar dependensi kanthi jeneng lan path, kaya iki:

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

Kita bisa extract kabeh dalan lan feed menyang printah Rektor, kang banjur bakal proses project kita src/ folder plus folder sing ngemot kabeh dependensi kanggo produksi:

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

Peningkatan luwih bisa nyegah Rektor ngolah dependensi sing wis nggunakake versi PHP target. Yen perpustakaan wis dikode nganggo PHP 7.1 (utawa versi apa wae ing ngisor iki), mula ora perlu transpile menyang PHP 7.1.

Kanggo nggayuh iki, kita bisa entuk dhaptar perpustakaan sing mbutuhake PHP 7.2 lan ndhuwur lan mung ngolah perpustakaan kasebut. Kita bakal entuk jeneng kabeh perpustakaan kasebut liwat Composer's why-not printah, kaya iki:

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

Amarga printah iki ora bisa karo --no-dev flag, kanggo kalebu mung dependensi kanggo produksi, kita kudu mbusak dependensi kanggo pembangunan lan regenerate autoloader, nglakokaké printah, banjur nambah maneh:

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

Komposer info --path printah njupuk path kanggo paket, karo format iki:

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

Kita nglakokaké printah iki kanggo kabeh item ing dhaftar kita kanggo njupuk kabeh path kanggo transpile:

Perlu solusi hosting sing menehi keunggulan kompetitif? BehmasterSampeyan wis dijamin karo kacepetan luar biasa, keamanan paling canggih, lan skala otomatis. Priksa rencana kita

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

Pungkasan, kita menehi dhaptar iki kanggo Rektor (plus project's src/ folder):

vendor/bin/rector process src $paths

Pitfalls kanggo Ngindhari Nalika Transpiling Kode

Kode transpiling bisa dianggep minangka seni, asring mbutuhake tweak khusus kanggo proyek kasebut. Ayo ndeleng sawetara masalah sing bisa ditindakake.

Aturan Rante Ora Tansah Diproses

Aturan chained yaiku nalika aturan kudu ngowahi kode sing diprodhuksi dening aturan sadurunge.

Contone, perpustakaan symfony/cache ngemot kode iki:

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

Nalika transpiling saka PHP 7.4 kanggo 7.3, fungsi tag kudu ngalami rong modifikasi:

  • Jinis bali ItemInterface kudu diowahi dhisik self, amarga aturan DowngradeCovariantReturnTypeRector
  • Jinis bali self banjur kudu dibusak, amarga aturan DowngradeSelfTypeDeclarationRector

Asil pungkasan kudu kaya iki:

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

Nanging, Rektor mung ngasilake tahap menengah:

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

Masalahe, Rektor ora bisa tansah ngontrol urutan aturan sing ditrapake.

Solusi kanggo ngenali aturan sing dirantai sing ora diproses, lan nglakokake Rektor anyar kanggo ngetrapake.

Kanggo ngenali aturan sing dirantai, kita mbukak Rektor kaping pindho ing kode sumber, kaya iki:

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

Kaping pisanan, kita mbukak Rektor kaya sing dikarepake, kanggo nindakake transpiling. Kapindho, kita nggunakake --dry-run flag kanggo nemokake yen isih ana owah-owahan sing kudu ditindakake. Yen ana, printah kasebut bakal metu kanthi kode kesalahan, lan output "beda" bakal nuduhake aturan sing isih bisa ditrapake. Tegese puteran pisanan ora rampung, kanthi sawetara aturan sing dirantai ora diproses.

Rektor Running karo --dry-run flag
Rektor Running with –dry-run flag

Sawise kita wis nemtokake aturan chained (utawa aturan) sing ora ditrapake, kita bisa nggawe file konfigurasi Rektor liyane - contone, rector-chained-rule.php bakal nglakokake aturan sing ilang. Tinimbang ngolah set lengkap aturan kanggo kabeh file ing src/, wektu iki, kita bisa mbukak aturan tartamtu sing ilang ing file tartamtu sing kudu diterapake:

// rector-chained-rule.php
use RectorCoreConfigurationOption;
use RectorDowngradePhp74RectorClassMethodDowngradeSelfTypeDeclarationRector;
use SymfonyComponentDependencyInjectionLoaderConfiguratorContainerConfigurator;

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',
  ]);
};

Akhire, kita marang Rektor ing pass kapindho kanggo nggunakake file config anyar liwat input --config:

# 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.php

Ketergantungan Komposer Bisa Ora Konsisten

Pustaka bisa nyatakake ketergantungan sing bakal dijadwalake kanggo pembangunan (mis require-dev in composer.json), nanging isih, referensi sawetara kode saka wong-wong mau kanggo produksi (kayata ing sawetara file ing ngisor iki src/, ora tests/).

Biasane, iki ora dadi masalah amarga kode kasebut bisa uga ora dimuat nalika produksi, mula ora bakal ana kesalahan ing aplikasi kasebut. Nanging, nalika Rektor ngolah kode sumber lan dependensi kasebut, iki bakal mbuktekake manawa kabeh kode referensi bisa dimuat. Rektor bakal nggawe kesalahan yen ana file referensi sawetara potongan kode saka perpustakaan sing ora diinstal (amarga diumumake mung dibutuhake kanggo pangembangan).

Contone, kelas EarlyExpirationHandler saka komponen Cache Symfony ngleksanakake antarmuka MessageHandlerInterface saka komponen Messenger:

class EarlyExpirationHandler implements MessageHandlerInterface
{
    //...
}

Nanging, symfony/cache nyatakake symfony/messenger dadi ketergantungan kanggo pembangunan. Banjur, nalika mbukak Rektor ing proyek sing gumantung ing symfony/cache, bakal nggawe kesalahan:

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

Ana telung solusi kanggo masalah iki:

  1. Ing konfigurasi Rektor, skip ngolah file sing ngrujuk potongan kode kasebut:
return static function (ContainerConfigurator $containerConfigurator): void {
  // ...

  $parameters->set(Option::SKIP, [
    __DIR__ . '/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php',
  ]);
};
  1. Download perpustakaan sing ilang lan tambahake path sing bakal dimuat kanthi otomatis dening Rektor:
return static function (ContainerConfigurator $containerConfigurator): void {
  // ...

  $parameters->set(Option::AUTOLOAD_PATHS, [
    __DIR__ . '/vendor/symfony/messenger',
  ]);
};
  1. Apa proyek sampeyan gumantung ing perpustakaan sing ilang kanggo produksi:
composer require symfony/messenger

Transpiling lan Integrasi Terus-terusan

Kaya sing wis kasebut sadurunge, ing komputer pangembangan kita kudu nggunakake --dry-run flag nalika mlaku Rektor, utawa digunakake, kode sumber bakal overridden karo kode transpiled. Mulane, luwih cocok kanggo mbukak proses transpiling sing nyata sajrone integrasi terus-terusan (CI), ing ngendi kita bisa muter pelari sementara kanggo nglakokake proses kasebut.

Wektu sing cocog kanggo nglakokake proses transpiling yaiku nalika ngasilake rilis kanggo proyek kita. Contone, kode ing ngisor iki minangka alur kerja kanggo Tindakan GitHub, sing nggawe rilis plugin WordPress:

name: Generate Installable Plugin and Upload as Release Asset
on:
  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 }}

Alur kerja iki ngemot prosedur standar kanggo ngeculake plugin WordPress liwat Tindakan GitHub. Tambahan anyar, kanggo transpile kode plugin saka PHP 7.4 dadi 7.1, kedadeyan ing langkah iki:

      - 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

Digabungake, alur kerja iki saiki nindakake langkah-langkah ing ngisor iki:

  1. Priksa kode sumber kanggo plugin WordPress saka repositori, ditulis nganggo PHP 7.4
  2. Nginstal dependensi Composer sawijining
  3. Transpiles kode saka PHP 7.4 kanggo 7.1
  4. Ngowahi entri "Mbutuhake PHP" ing header file utama plugin saka "7.4" kanggo "7.1"
  5. Mbusak dependensi sing dibutuhake kanggo pangembangan
  6. Nggawe file .zip plugin, ora kalebu kabeh file sing ora dibutuhake
  7. Ngunggah file .zip minangka aset rilis (lan, saliyane, minangka artefak menyang Tindakan GitHub)

Nguji Kode Transpiled

Sawise kode wis transpiled kanggo PHP 7.1, carane kita ngerti sing bisa uga? Utawa, kanthi tembung liya, kepiye carane ngerti yen wis diowahi kanthi lengkap, lan ora ana sisa-sisa versi kode PHP sing luwih dhuwur?

Kaya transpiling kode, kita bisa ngleksanakake solusi ing proses CI. Ide iki kanggo nyiyapake lingkungan pelari nganggo PHP 7.1 lan mbukak linter ing kode transpiled. Yen ana potongan kode sing ora kompatibel karo PHP 7.1 (kayata properti sing diketik saka PHP 7.4 sing ora diowahi), mula linter bakal nggawe kesalahan.

Linter kanggo PHP sing bisa digunakake kanthi apik yaiku PHP Parallel Lint. Kita bisa nginstal perpustakaan iki minangka ketergantungan kanggo pangembangan ing proyek kita, utawa duwe proses CI nginstal minangka proyek Komposer mandiri:

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

Saben kode ngemot PHP 7.2 lan ndhuwur, PHP Parallel Lint bakal nggawe kesalahan kaya iki:

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.php
PHP 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 seconds
Syntax error found in 1 file

------------------------------------------------------------
Parse error: layers/GraphQLAPIForWP/plugins/graphql-api-for-wp/graphql-api.php:55
    53|     '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 55
Error: Process completed with exit code 1.

Ayo nambah linter menyang alur kerja CI kita. Langkah-langkah kanggo nglakokake transpile kode saka PHP 8.0 dadi 7.1 lan nyoba yaiku:

  1. Priksa kode sumber
  2. Supaya lingkungan mbukak PHP 8.0, supaya Rektor bisa interpretasi kode sumber
  3. Transpile kode menyang PHP 7.1
  4. Instal alat linter PHP
  5. Ganti versi PHP lingkungan menyang 7.1
  6. Mbukak linter ing kode transpiled

Alur kerja Tindakan GitHub iki nindakake tugas:

name: Downgrade PHP tests
jobs:
  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

Mangga sok dong mirsani sing sawetara bootstrap80.php file saka perpustakaan polyfill Symfony (sing ora perlu transpiled) kudu dipun tilar saka linter. File-file kasebut ngemot PHP 8.0, saengga linter bakal nggawe kesalahan nalika ngolah. Nanging, ora kalebu file kasebut aman amarga bakal dimuat ing produksi mung nalika mbukak PHP 8.0 utawa luwih dhuwur:

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

Apa sampeyan nggawe plugin umum kanggo WordPress utawa sampeyan nganyari kode warisan, ana akeh alasan sing nggunakake versi PHP paling anyar bisa uga ora mungkin 👩‍💻 Sinau carane transpiling bisa mbantu ing pandhuan iki 👇Klik kanggo Tweet

Summary

Artikel iki ngajari kita carane transpile kode PHP kita, ngidini kita nggunakake PHP 8.0 ing kode sumber lan nggawe release sing bisa digunakake ing PHP 7.1. Transpiling ditindakake liwat Rektor, alat rekonstruktor PHP.

Transpiling kode ndadekake kita dadi pangembang sing luwih apik amarga kita bisa nangkep kewan omo ing pangembangan lan ngasilake kode sing luwih gampang diwaca lan dingerteni.

Transpiling uga ngijini kita kanggo decouple kode kita karo syarat PHP tartamtu saka CMS. Saiki kita bisa nindakake yen pengin nggunakake versi PHP paling anyar kanggo nggawe plugin WordPress utawa modul Drupal sing kasedhiya kanggo umum tanpa mbatesi basis pangguna.

Apa sampeyan duwe pitakon babagan transpiling PHP? Ayo kita ngerti ing bagean komentar!

Artikel web

0 komentar
Umpan Balik Inline
Ndeleng kabeh komentar
Bali menyang ndhuwur tombol