Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP 8 and Legacy Code

PHP 8 and Legacy Code

Presented on January 21st 2021 at the PHPcc Online Conference.
https://thephp.cc/dates/2021/01/the-online-php-conference
---------------------------------------------------------------
With the release of PHP 8, unit tests have become more important than ever before as there are numerous changes which can only be detected via tests.

But what if you maintain a legacy project which is still using PHPUnit 5? And what about extensions to this software running integration tests using (parts of) your test set up?

Using WordPress as an example, let's take a look at how a legacy project can prepare for compatibility with PHP 8 and at the problems they run into when paying up some of their technical debt. What are the extra complications they run into? And how to set priorities with the added time pressure of the PHP 8 release being around the corner?
---------------------------------------------------------------

Juliette Reinders Folmer

January 21, 2021
Tweet

More Decks by Juliette Reinders Folmer

Other Decks in Programming

Transcript

  1. PHP 8 and Legacy Code A case-study Juliette Reinders Folmer

    Tweet about it: @jrf_nl #OnlinePHPConference © Sebastian Bergmann
  2. New in PHP 8.0 Match control structure Attributes Nullsafe object

    operator Trailing comma in closure use Constructor property promotion Non capturing catch Union types Mixed type Static return type Throw expressions Stringable Magic method signature check Stable sorting ::class on objects Syntax tweaks Named arguments Reclassify engine warnings Saner numeric strings Saner string to number comparisons Locale independent float to string cast Stricter type check for arithmetic/ bitwise operators Consistent type errors for internal functions "bug fixes"
  3. An Example <?php declare(strict_types = 1); vprintf( 'The %s', 'dog'

    ); vprintf( 'The %s', ['dog'] ); PHP < 8.0 PHP 8.0 The dog Uncaught TypeError: vprintf(): The dog Argument #2 ($values) must be of type array, string given
  4. “ As a rare exception, this BC break will probably

    hit php-src harder than actual users of PHP "Backward Incompatible Changes" as per the Consistent type errors for internal functions RFC
  5. Another example <?php $sub = substr('abcdef', 4, -4); if ($sub

    === false) { echo 'fail'; } else { echo 'do something with $sub'; } PHP < 8.0 PHP 8.0 fail do something with $sub
  6. PHP 8 Compatibility Checklist ❑ Wait for PHP 8 compatible

    tooling ❑ Get the test suite running on PHP 8 ❑ Run static analysis ❑ Fix every issue ❑ Update external dependencies ❑ Review public parameter names
  7. PHPUnit vs PHP PHPUnit / PHP 5.6 7.0 7.1 7.2

    7.3 7.4 8.0 5.x 6.x 7.x 8.x 9.x 9.3+ void
  8. Testing WordPress on PHP 8 July August September October November

    December First PHP 8 tickets opened Drop PHP < 7.1 ?
  9. Testing WordPress on PHP 8 July August September October November

    December First PHP 8 tickets opened Drop PHP < 7.1 ? Fixed rolling schedule proposal
  10. Constraints and Roadblocks ▪ Supporting PHP 5.6 + 7.0 still

    required ▪ Plugin tests often extend WP integration test suite ▪ PHPUnit < 9.3 not compatible with PHP 8.0 - Mocking - @runInSeparateProcess ▪ PHPUnit 7 Phar will not run on PHP 8.0 ▪ Committed composer.lock file
  11. Solution "autoload-dev": { "files": [ "tests/includes/MockObject/Builder/NamespaceMatch.php", "tests/includes/MockObject/Builder/ParametersMatch.php", "tests/includes/MockObject/InvocationMocker.php", "tests/includes/MockObject/MockMethod.php" ],

    "exclude-from-classmap": [ "vendor/phpunit/…/MockObject/Builder/NamespaceMatch.php", "vendor/phpunit/…/MockObject/Builder/ParametersMatch.php", "vendor/phpunit/…/MockObject/InvocationMocker.php", "vendor/phpunit/…/MockObject/MockMethod.php" ] }, ▪ Composer, not phar ▪ Lock at PHPUnit 7.5 ▪ Downgrade to PHPUnit 5 in CI for PHP 5.6, 7.0 ▪ Use MockObject classes from PHPUnit 9.3 ▪ Separate process => separate group
  12. Testing WordPress on PHP 8 July August September October November

    December First PHP 8 tickets opened Drop PHP < 7.1 ? Fixed rolling schedule proposal Tests running on PHP 8 Tests passing on PHP 8
  13. Testing WordPress on PHP 8 July August September October November

    December First PHP 8 tickets opened Drop PHP < 7.1 ? Fixed rolling schedule proposal Tests running on PHP 8 Tests passing on PHP 8 WP/ PHP 8 compat report External dependency updates WP.5.6 released "beta" compatible with PHP 8
  14. "beta-compatible" Fix all KNOWN issues Undiscovered issues ? Parameter name

    review Plugins & themes not being compatible Plugins & themes doing it wrong™
  15. Mock-based Tests PHPUnit 5.x composer.lock Platform - php 5.6 PHPUnit

    5.x – 9.x CI: composer update … --ignore-platform-reqs Needs PHPUnit cross-version compatibility layer
  16. WP Integration Tests PHPUnit 5.x composer.lock Platform - php 5.6

    PHPUnit 5.x – 7.x CI: composer update … --ignore-platform-reqs Need PHPUnit cross-version compatibility layer Need custom autoload for MockObject
  17. New Tooling PHPUnit Polyfills WP Test Utils Sponsored by: Alternative:

    Symfony Bridge * Supports PHPUnit 4.8 – 9.x, PHP 5.5 – 8.0
  18. “ The barrier for updating legacy code to use a

    more modern PHP version has gone up exponentially and for some, may even have become insurmountable. Juliette Reinders Folmer "A Perfect Storm"
  19. Further Reading ▪ The 2020 WordPress and PHP 8 Compatibility

    Report https://developer.yoast.com/blog/the-2020-wordpress-and-php-8- compatibility-report/ ▪ A Perfect Storm https://24daysindecember.net/2020/12/21/a-perfect-storm/ ▪ PHPUnit Polyfills https://packagist.org/packages/yoast/phpunit-polyfills ▪ WP Test Utils https://packagist.org/packages/yoast/wp-test-utils