{"id":69661,"date":"2022-12-21T09:01:56","date_gmt":"2022-12-21T09:01:56","guid":{"rendered":"https:\/\/www.cryptocabaret.com\/?p=69661"},"modified":"2022-12-21T09:01:56","modified_gmt":"2022-12-21T09:01:56","slug":"how-to-migrate-your-code-from-php-7-4-to-8-1","status":"publish","type":"post","link":"https:\/\/www.cryptocabaret.com\/?p=69661","title":{"rendered":"How to migrate your code from PHP 7.4 to 8.1"},"content":{"rendered":"<p><span class=\"field field--name-title field--type-string field--label-hidden\">How to migrate your code from PHP 7.4 to 8.1<\/span><br \/>\n<span class=\"field field--name-uid field--type-entity-reference field--label-hidden\"><a title=\"View user profile.\" href=\"https:\/\/opensource.com\/users\/gilzow\" class=\"username\">gilzow<\/a><\/span><br \/>\n<span class=\"field field--name-created field--type-created field--label-hidden\">Wed, 12\/21\/2022 &#8211; 03:00<\/span><\/p>\n<div class=\"clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item\">\n<p>The end-of-life (EOL) for <a href=\"https:\/\/www.php.net\/eol.php\">PHP 7.4<\/a> was Monday, November 28, 2022. If you\u2019re like me, that date snuck up much faster than anticipated. While your PHP 7.4 code isn\u2019t going to immediately stop working, you do need to begin making plans for the future of this codebase.<\/p>\n<h2>What are your options?<\/h2>\n<p>You could continue to remain on PHP 7.4, but there are several benefits to updating. The biggest are security\u00a0risk and support. As we move farther and farther away from the EOL date, attackers will turn their focus to PHP 7.4 knowing that any vulnerabilities they discover will go unpatched in the majority of systems. Staying on PHP 7.4 drastically increases the risk of your site being compromised in the future. In a similar vein, finding support for issues you encounter with PHP 7.4 will become increasingly more difficult. In addition, you will most likely begin to encounter compatibility issues with third-party code\/packages as they update their code to be compatible with later versions and drop support for 7.4. You\u2019ll also be missing out on significant speed and performance improvements <a href=\"https:\/\/platform.sh\/blog\/2020\/php-80-feature-focus-just-in-time-compilation\">introduced in 8.0<\/a> and further <a href=\"https:\/\/platform.sh\/blog\/2021\/php-81-lays-new-ground-at-platformsh\">improved in 8.1<\/a>. But upgrading all that legacy code is daunting!<\/p>\n<h2>Where to start?<\/h2>\n<p>Luckily, PHP provides an <a href=\"https:\/\/www.php.net\/manual\/en\/migration80.php\">official migration guide<\/a> from PHP 7.4 to 8.0 to get you started (and an <a href=\"https:\/\/www.php.net\/manual\/en\/migration81.php\">8.0 to 8.1 migration guide<\/a> as well). Be sure to read through the Backward Incompatible Changes and Deprecated Features sections. While these guides are incredibly handy, you may very well have tens of thousands of lines of code to check, some of which you may have inherited. Luckily there are some options to help pinpoint potential problem areas in the migration.<\/p>\n<h3>PHPCodeSniffer + PHPCompatibility sniffs<\/h3>\n<p><a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\">PHPCodeSniffer<\/a> (PCS) is a package for syntax checking of PHP Code. It checks your code against a collection of defined rules (aka \u201csniffs\u201d) referred to as \u201cstandards\u201d. PHPCodeSniffer ships with a collection of standards you can use including PEAR, PSR1, PSR2, PSR12, Squiz, and Zend. Luckily, you can write your own collection of sniffs to define any set of rules you like.<\/p>\n<blockquote>\n<p>PHPCompability has entered the chat<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/github.com\/PHPCompatibility\/PHPCompatibility\">PHPCompatibility<\/a> \u201cis a set of sniffs for PHP CodeSniffer that checks for PHP cross-version compatibility\u201d allowing you to test your codebase for compatibility with different versions of PHP, including PHP 8.0 and 8.1. This means you can use PHPCodeSniffer to scan your codebase, applying the rules from PHPCompability to sniff out any incompatibilities with PHP 8.1 that might be present.<\/p>\n<h2>Before I continue\u2026<\/h2>\n<p>While PHP8.2 was released on <a href=\"https:\/\/www.php.net\/archive\/2022.php#2022-12-08-1\">December 8, 2022<\/a>, and I encourage you to begin looking over the <a href=\"https:\/\/www.php.net\/manual\/en\/migration82.php\">official 8.1 to 8.2 migration guide<\/a> and begin making plans to upgrade, most of the checkers I mention in this article have not completed full support for 8.2 at this time. For those reasons, I\u2019ll be focusing on migrating the code to PHP8.1, and not 8.2.<\/p>\n<p>In the process of writing this article, I discovered PHPCompatiblity has a <a href=\"https:\/\/github.com\/PHPCompatibility\/PHPCompatibility\/issues\/1344\">known issue<\/a> when checking for compatibility with PHP 8.0\/8.1 where it will report issues that should be <strong>Errors<\/strong> as <strong>Warnings<\/strong>. The only workaround for now is to use the <code>develop<\/code> branch for PHPCompatibility instead of <code>master<\/code>. While they state it is stable, please be aware that in this article, I\u2019m using the non-stable branch. You may want to weigh the pros and cons of using the <code>develop<\/code> branch before implementing it anywhere else than in a local development environment. While I found PCS+PHPCompatibility to be the most straightforward and comprehensive solution for checking for incompatible code, if you do not want to use a non-stable version of PCS, see the section at the end of the article about alternative options.<\/p>\n<p>For the purposes of this article, I\u2019ll be using the <a href=\"https:\/\/github.com\/simplesamlphp\/simplesamlphp\/releases\/tag\/v1.14.6\">1.4.6 version of SimpleSAMLphp<\/a> to test for incompatibilities. This is a six-year-old version of the code base. I do this not to pick on SimpleSAMLphp, but because I wanted something that would <em>definitely<\/em> have some errors. As it turns out, all of the platform.sh code I tested, as well as my own code was already compatible with PHP8.1 and required no changes.<\/p>\n<h2>Get started<\/h2>\n<p>To get started, first clone your codebase, and then create a new branch. You\u2019ll now need to decide if you want to install the dependencies and run the scans on your local machine or in a local development environment using something like <a href=\"https:\/\/opensource.com\/article\/22\/12\/ddev\" target=\"_blank\" rel=\"noopener\">DDEV<\/a>, <a href=\"https:\/\/lando.dev\/\">Lando<\/a>, or\u00a0<a href=\"https:\/\/docksal.io\/\">Docksal<\/a>. In this demo, I\u2019m using DDEV. I suggest using a local development environment vs running directly on your local machine because while it\u2019s not required to use the version of PHP you want to test against, for the best results, it is recommended you do so. If you don\u2019t have PHP installed, or don\u2019t have the target version installed, a local development environment allows you to create an ephemeral environment with exactly what you need without changing your machine.<\/p>\n<p>After setting up your environment for PHP 8.1, at a terminal prompt (in my case, I\u2019ve run <code>ddev start<\/code> and once the containers are available, shell into the web app using <code>ddev ssh<\/code>), you need to add these new packages so you use them to test with. I\u2019ll be adding them with composer, however, there are <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer#phive\">multiple<\/a> <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer#git-clone\">ways<\/a> to <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer#installation\">install<\/a> <a href=\"https:\/\/github.com\/PHPCompatibility\/PHPCompatibility#installation-via-a-git-check-out-to-an-arbitrary-directory-method-2\">them<\/a> if you would prefer to do so differently. If your codebase isn\u2019t already using composer, you\u2019ll need to do <a href=\"https:\/\/getcomposer.org\/doc\/03-cli.md#init\">composer init<\/a> before continuing.<\/p>\n<p>Because you&#8217;ll be using the develop branch of PHPCompatibility there are a couple of extra steps to do that aren\u2019t in the regular installation instructions. First is that the develop branch of PHPCompatibility requires an alpha version of <code>phpcsstandards\/phpcsutils<\/code>. Because it is marked as alpha, you&#8217;ll need to let composer know this one package is OK to install even though it is below your minimum stability requirements.<\/p>\n<p><code>$ composer require --dev phpcsstandards\/phpcsutils:\"^1.0@dev\"<\/code><\/p>\n<p>Next, install PHPCompatibility targeting the <code>develop<\/code> branch<\/p>\n<p><code>$ composer require --dev phpcompatibility\/php-compatibility:dev-develop<\/code><\/p>\n<p>The <code>develop<\/code> branch also installs <code>dealerdirect\/phpcodesniffer-composer-installer<\/code> so you don\u2019t need to add it manually or direct PCS to this new standard.<\/p>\n<p>To verify our new standards are installed, you&#8217;ll have PCS display the standards it is aware of.<\/p>\n<pre>\n<code>$ phpcs -i\nThe installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, PHPCompatibility, PHPCS23Utils and PHPCSUtils<\/code><\/pre>\n<p>Now that you know your standards are available, you can have PCS scan our code. To instruct PCS to use a specific standard, use the <code>--standard<\/code> option and tell it to use <code>PHPCompatibility<\/code>. However, you also need to tell PHPCompatibility which PHP version you want to test against. For that, use PCS\u2019 <code>--runtime-set<\/code> option and pass it the key <code>testVersion<\/code> and value of <code>8.1<\/code>.<\/p>\n<p>Before you start the scan, the one issue remaining is that code you want to scan is in the root of the project (<code>.<\/code>) but the <code>vendor<\/code> directly is also in the project root. You don\u2019t want the code in <code>vendor<\/code> scanned, as those aren\u2019t packages you necessarily control. PCS allows you to tell it to not scan files\/directories with the <code>--ignore<\/code> option. Finally, you want to see the progress as PCS parses the file so you&#8217;ll pass in the <code>-p<\/code> option.<\/p>\n<p>Putting it all together:<\/p>\n<p><code>$ phpcs -p . --standard=PHPCompatibility --runtime-set testVersion 8.1 --ignore=*\/vendor\/*<\/code><\/p>\n<p>This kicks off PCS which will output its progress as it scans through your project\u2019s code. <code>W<\/code> indicates <strong>Warnings<\/strong>, and <code>E<\/code> indicates <strong>Errors<\/strong>. At the end of the scan it will output: a full report with the file containing the issue, the line number where the issue occurs, whether the issue is a <strong>Warning<\/strong> or an <strong>Error<\/strong>, and the specific issue discovered.<\/p>\n<p>In general, <strong>Errors<\/strong> are things that will cause a fatal error in PHP 8.1 and will need to be fixed before you can migrate. <strong>Warnings<\/strong> can be things that have been deprecated in 8.0\/8.1 but not yet removed or issues that PCS ran into while trying to parse the file.<\/p>\n<p><a href=\"https:\/\/asciinema.org\/a\/MGKsC3RkNaWMcGtJGiyMHorWy\"><img decoding=\"async\" alt=\"asciicast\" src=\"https:\/\/asciinema.org\/a\/MGKsC3RkNaWMcGtJGiyMHorWy.svg\"><\/a><\/p>\n<p>Given that the report might be long, and is output all at once into your terminal, there are <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\/wiki\/Reporting\">numerous options<\/a> for changing the information that is included in the report, as well as multiple reporting formats.<\/p>\n<p>As you begin to fix your code, you can rerun the report as many times as needed. However, at some point, you\u2019ll need to test the code on an actual PHP8.1 environment with real data. If you\u2019re using <a href=\"https:\/\/platform.sh\/\">Platform.sh<\/a>, which is as easy as creating a branch, changing a single line in your configuration file, and pushing that branch to us. You can check out <a href=\"https:\/\/www.youtube.com\/watch?v=mAb8DO7Jp0Q\">this video<\/a> to see how easy it is!<\/p>\n<h2>There\u2019s too much to fix!<\/h2>\n<p>Now that you have a solid idea of what needs to be updated before you can migrate, you might be facing an incredible amount of work ahead of you. Luckily, you have some options to help you out. PCS ships with a code fixer called <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\/wiki\/Fixing-Errors-Automatically#using-the-php-code-beautifier-and-fixer\">PHP Code Beautifier and Fixer<\/a> (<code>phpcbf<\/code>). Running phpcbf is almost identical to running phpcs and most of the options are identical. The other option is <a href=\"https:\/\/github.com\/rectorphp\/rector\">Rector<\/a>. Usage of these tools is beyond the scope of this article, but as with any automation, you\u2019ll want to test and verify before promoting changes to production.<\/p>\n<\/p>\n<div class=\"embedded-resource-list callout-float-right\">\n<div class=\"field field--name-title field--type-string field--label-hidden field__item\">Programming and development<\/div>\n<div class=\"field field--name-links field--type-link field--label-hidden field__items\">\n<div class=\"field__item\"><a href=\"https:\/\/developers.redhat.com\/?intcmp=7016000000127cYAAQ\">Red Hat Developers Blog<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/downloads\/cheat-sheets?intcmp=7016000000127cYAAQ\">Programming cheat sheets<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/www.redhat.com\/en\/services\/training\/learning-subscription?intcmp=7016000000127cYAAQ\">Try for free: Red Hat Learning Subscription<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/downloads\/bash-programming-guide?intcmp=7016000000127cYAAQ\">eBook: An introduction to programming with Bash<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/developers.redhat.com\/cheat-sheets\/bash-shell-cheat-sheet?intcmp=7016000000127cYAAQ\">Bash shell scripting cheat sheet<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/developers.redhat.com\/e-books\/modernizing-enterprise-java?intcmp=7016000000127cYAAQ\">eBook: Modernizing Enterprise Java<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/downloads\/building-applications?intcmp=7016000000127cYAAQ\">An open source developer&#8217;s guide to building applications<\/a><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<h2>Alternative options<\/h2>\n<p>If for any reason you don\u2019t feel comfortable using a non-stable version of PCS, you do have other options for checking your code.<\/p>\n<h3><a href=\"https:\/\/github.com\/phan\/phan\">Phan<\/a><\/h3>\n<p>Phan is a static code analyzer for PHP. It offers multiple levels of analysis and allows for incrementally strengthening that analysis.<\/p>\n<p>\u201cStatic analysis needs to be introduced slowly if you want to avoid your team losing their minds.\u201d<\/p>\n<p>Phan doesn\u2019t target just compatibility with newer versions, it can highlight areas of code that will error in later versions. However, there are some caveats when using Phan for checking compatibility:<\/p>\n<ul>\n<li>Slower than PCS+PHPCompatibility.<\/li>\n<li>Phan requires the <a href=\"https:\/\/github.com\/nikic\/php-ast\">ast php extension<\/a> which is not available by default on Platform.sh (or in DDEV). You\u2019ll need to install it in your local development environment and add it to your php.ini file. Alternatively, you can use the <code>--allow-polyfill-parser<\/code> option, but it is considerably slower.<\/li>\n<li>Phan\u2019s default reporting output isn\u2019t as easy to read as other options<\/li>\n<li>I came across an issue where if your code base sets a different <code>vendor<\/code> directory via composer\u2019s <code>[config:vendor-dir](https:\/\/getcomposer.org\/doc\/06-config.md#vendor-dir)<\/code> option, it will error out stating it can\u2019t find certain files in the <code>vendor<\/code> directory<\/li>\n<li>As mentioned, Phan analyzes much more than just PHP8.1 compatibility. While certainly a strength in other situations, if your goal is to migrate from 7.4 to 8.1 as quickly as possible, you will have to parse through errors that are unrelated to version compatibility.<\/li>\n<li>Requires you run it on the PHP version you want to target<\/li>\n<\/ul>\n<h3><a href=\"https:\/\/phpstan.org\/\">PHPStan<\/a><\/h3>\n<p>Similar to Phan, PHPStan is a static code analyzer for PHP that promises to \u201cfind bugs without writing tests.\u201d And a similar set of caveats apply:<\/p>\n<ul>\n<li>Slower than either PCS or Phan<\/li>\n<li>Analyzes much more than just PHP8.1 compatibility so depending on your current codebase, you will have to possibly parse through a bunch of errors that are unrelated to version compatibility<\/li>\n<li>Requires you run it on the PHP version you want to target<\/li>\n<\/ul>\n<h3><a href=\"https:\/\/github.com\/php-parallel-lint\/PHP-Parallel-Lint\">PHP Parallel Lint<\/a><\/h3>\n<p>A very fast PHP linter that can lint your codebase for issues, but can also check for deprecations. While it is exceptionally fast, it is only a linter, and therefore can only surface deprecations that are thrown at compile time, not at runtime. In my example code, it only found 2 deprecations vs the 960 deprecations PCS uncovered.<\/p>\n<h2>Summary<\/h2>\n<p>Code migrations, while never fun, are crucial to minimizing organizational risk. Platform.sh gives you the flexibility to test your code using the same data and configurations as your production site, but in a siloed environment. Combine this with the tools above, and you have everything you need for a strong, efficient code migration.<\/p>\n<hr>\n<p><em>This article originally published on the <a href=\"https:\/\/community.platform.sh\/t\/migrating-php-7-4-code-to-8-1-on-platform-sh\/1156\" target=\"_blank\" rel=\"noopener\">Platform.sh community site<\/a> and has been republished with permission.<\/em><\/p>\n<\/div>\n<div class=\"clearfix text-formatted field field--name-field-article-subhead field--type-text-long field--label-hidden field__item\">\n<p>With the recent end-of-life for PHP 7.4, it&#8217;s time to migrate your code. Here are a few options to do that.<\/p>\n<\/div>\n<div class=\"field field--name-field-lead-image field--type-entity-reference field--label-hidden field__item\">\n<article class=\"media media--type-image media--view-mode-caption\">\n<div class=\"field field--name-field-media-image field--type-image field--label-hidden field__item\">  <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.cryptocabaret.com\/wp-content\/uploads\/2022\/12\/fail_progress_cycle_momentum_arrow.png\" width=\"520\" height=\"292\" alt=\"arrows cycle symbol for failing faster\" title=\"arrows cycle symbol for failing faster\"><\/div>\n<div class=\"field field--name-field-caption field--type-text-long field--label-hidden caption field__item\"><span class=\"caption__byline\">Image by: <\/span><\/p>\n<p>Opensource.com<\/p>\n<\/div>\n<\/article>\n<\/div>\n<div class=\"field field--name-field-tags field--type-entity-reference field--label-hidden field__items\">\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/tags\/drupal\" hreflang=\"en\">Drupal<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/tags\/web-development\" hreflang=\"en\">Web development<\/a><\/div>\n<div class=\"field__item\"><a href=\"https:\/\/opensource.com\/tags\/wordpress\" hreflang=\"en\">WordPress<\/a><\/div>\n<\/p><\/div>\n<div class=\"hidden field field--name-field-listicle-title field--type-string field--label-hidden field__item\">What to read next<\/div>\n<div class=\"field field--name-field-default-license field--type-list-string field--label-hidden field__item\"><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\"><br \/>\n        <img decoding=\"async\" alt=\"Creative Commons License\" src=\"https:\/\/www.cryptocabaret.com\/wp-content\/uploads\/2022\/12\/cc-by-sa--45.png\" title=\"This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.\"><\/a>This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.<\/div>\n<section class=\"field field--name-field-comments field--type-comment field--label-hidden comment-wrapper\">\n<div class=\"comments__count\">\n<div class=\"login\"><a href=\"https:\/\/opensource.com\/user\/register?absolute=1\">Register<\/a> or <a href=\"https:\/\/opensource.com\/user\/login?destination=\/feed&amp;absolute=1\">Login<\/a> to post a comment.<\/div>\n<\/p><\/div>\n<\/section>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\" rel=\"noopener\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to migrate your code from PHP 7.4 to 8.1 gilzow Wed, 12\/21\/2022 &#8211; 03:00 The end-of-life (EOL) for PHP 7.4 was Monday, November 28, 2022. If you\u2019re like me, that date snuck up much faster than anticipated. While your PHP 7.4 code isn\u2019t going to immediately stop working, you do need to begin making [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":69662,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[307],"tags":[],"class_list":["post-69661","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-open-source"],"_links":{"self":[{"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/posts\/69661","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=69661"}],"version-history":[{"count":0,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/posts\/69661\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=\/wp\/v2\/media\/69662"}],"wp:attachment":[{"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=69661"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=69661"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cryptocabaret.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=69661"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}