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

For the love of code: Modernizing WordPress, plugins, and themes

For the love of code: Modernizing WordPress, plugins, and themes

Presented on June 21st 2019 at WordCamp Europe, Berlin, Germany.
https://2019.europe.wordcamp.org/
---------------------------------------------------------------
Now that WordPress has committed to a minimum requirement of PHP 7 by the end of 2019, we can all start looking at modernizing the code we maintain. Removing hacks to support old versions is easy, but how can code be improved when it just works on PHP 7? Namespaces, generators, Intl are just a few of the features introduced since PHP 5.2, not to mention scalar type declarations and all the other awesomeness that came with PHP 7. But what does it all mean, and how can you take advantage of these goodies? Join Juliette to learn to identify where to make quick fixes, when to look into refactoring, and how to make your code faster, better and more secure by using modern PHP.

Juliette Reinders Folmer

June 21, 2019
Tweet

More Decks by Juliette Reinders Folmer

Other Decks in Programming

Transcript

  1. For the Love of Code:
    Modernizing WordPress, plugins and themes
    Juliette Reinders Folmer
    Tweet about it: @jrf_nl #ForTheLoveOfCode #WCEU

    View Slide

  2. Olivier Gobet

    View Slide

  3. PHP Supported Versions

    View Slide

  4. WordPress versus PHP
    4.2 4.3 4.4 5.0 5.1 5.2 5.3 5.4 5.5 5.6 7.0 7.1 7.2 7.3 7.4
    WP 2.0 Dec 2005
    WP 2.5 Mar 2008
    WP 3.2 July 2011 5.2.4
    ...
    WP 5.2 May 2019 5.6.20
    WP 5.? Dec 2019

    View Slide

  5. Let's
    Modernize
    All The Things!!

    View Slide

  6. But the
    code
    works
    fine on
    PHP 7...
    munozgo

    View Slide

  7. Lower Memory
    Usage
    Enhanced
    Interoperability
    New Features
    Future
    Maintainability
    Improve(d)
    Security
    Better
    Performance
    Why Modernize ?

    View Slide

  8. EricBerthe 
    kconnors 

    View Slide

  9. The fact that
    code runs on
    PHP 5.6+,
    does not make
    it PHP 5.6+
    code
    BryanHanson

    View Slide

  10. Let's Rewrite from
    Scratch!

    View Slide

  11. Let's not
     Halts Progress
     Maintaining BC will be
    much more difficult
    quicksandala

    View Slide

  12. All Code
    is Legacy Code
    as soon as it is written

    View Slide

  13. mxruben

    View Slide

  14. What Needs to be Done ?
    Fix
    Incompati-
    bilities
    Use What
    Can Already
    be Used
    Clean Up Modernize
    Implement
    Quick Fixes
    Selectively
    Refactor

    View Slide

  15. Fix Existing
    Incompatibilities
     PHP -l (lint)
     PHPCompatibility
     phan
     php7cc
     php7mar
     php-compat-info
    Seemann

    View Slide

  16. Use What Can Already
    be Used
    PHP Native features
    like:
     Autoloading
     Exceptions with
    try/catch
     instanceof
     Filter
     SPL (Stnd PHP Library)
     mysqli or PDO
     Class name based type
    declarations
     Array type declarations
    WP Polyfilled features
    like:
     Sodium
     CSPRNG (random_bytes(),
    random_int())
     Various MbString functions
     hash_equals()
     JsonSerializable interface
     spl_autoload_register()
     array_replace_recursive()
     is_iterable()
     is_countable()

    View Slide

  17. Clean Up
    (code-level)

    View Slide

  18. Remove Hacks
    and Polyfills
     version_compare()
     extension_loaded()
     class_exists()
     method_exist()
     function_exists()
     defined()
     phpversion()
     class_alias()
     PHP_VERSION_ID
     PHP_MAJOR_VERSION
     PHP_MINOR_VERSION Lilla Frerichs

    View Slide

  19. Use case-insensitive
    searches.

    View Slide

  20. Look Behind:
    Code for the now, but
    allow for the past
    Look Forward:
    Code for the lowest
    common denominator
    and allow for the future.

    View Slide

  21. Looking Forward vs Looking Behind
    if ( version_compare( phpversion(), '7.0', '>' ) ) {
    // Modern code.
    }
    // Old code.
    if ( version_compare( PHP_VERSION_ID, '59999', '<=' ) ) {
    // Back-fill for missing feature. Remove when ...
    }
    // More modern code.

    View Slide

  22. Clean Up
    (application-level)

    View Slide

  23. Use PHPUnit 5.4+ // Works with PHPUnit 3/4/5.
    class MyTest extends
    PHPUnit_Framework_TestCase { }
    // Works with PHPUnit 5.4/6/7.
    use PHPUnit\Framework\TestCase;
    class MyTest extends TestCase { }
    v Compatible with:
    8 PHP 7.2, 7.3, 7.4
    (support ends Feb 2021)
    7 PHP 7.1, 7.2, 7.3
    (support ends Feb 2020)
    6 PHP 7.0, 7.1, 7.2
    5 PHP 5.6, 7.0, 7.1
    4 PHP 5.3, 5.4, 5.5, 5.6

    View Slide

  24. Use Composer
    {
    "name": "organization/my-plugin",
    "description": "A plugin...",
    "keywords": ["wordpress"],
    "license": "GPL-2.0-or-later",
    "type": "wordpress-plugin",
    "require": {
    "php": "^5.6.20 || ^7.0",
    },
    "require-dev": {
    "humbug/php-scoper": "^0.6.0"
    },
    "autoload": {
    "classmap": [
    "src/"
    ]
    }
    }
     ... but prevent
    dependency conflicts

    View Slide

  25. Modernize

    View Slide

  26. Best Practices
     Focus on function, not
    syntax
    GaborfromHungary

    View Slide

  27. Best Practices
     Focus on function, not
    syntax
     Test Driven
    Refactoring
    GaborfromHungary

    View Slide

  28. Test Driven Refactoring
    Are there tests ? Do the tests actually
    cover the code ?
    Are the tests not
    just testing the
    "happy path" ?

    View Slide

  29. Best Practices
     Focus on function, not
    syntax
     Test Driven
    Refactoring
     Don't attempt to do
    everything at once
    GaborfromHungary

    View Slide

  30. Approaches to Modernizing
    Horizontal
    • File by file
    • Component-led
    Vertical
    • Fix by fix
    • PHP feature-led

    View Slide

  31. Best Practices
     Focus on function, not
    syntax
     Test Driven
    Refactoring
     Don't attempt to do
    everything at once
     Use the tools available
    GaborfromHungary

    View Slide

  32. Tools
    Psalm
    PHPStan
    Phan
    Exakat
    PHPModernizer
    (upcoming)
    Rector
    PHPStorm
    Inspections
    PHPMD
    (Mess Detector)
    and many more...

    View Slide

  33. Spread Operator
    Iterators &
    Generators
    Traits
    Namespaces
    Constant Scalar
    Expressions
    Quick Fixes
    Short Ternary &
    Null coalesce
    Type
    Declarations
    5.3 5.4 5.6
    5.3, 7.0, 7.4 5.0, 5.4, 7.0 – 7.2
    5.6 5.2 - 5.5
    5.3 - 7.4

    View Slide

  34. Namespaces
    Seemann
    5.3

    View Slide

  35. Logical Grouping
    of Code

    View Slide

  36. Before You Start
     Think
     Autoloading ?
    - PSR-0 (deprecated)
    - PSR-4
    - Custom
    - Classmap
    ngrigor

    View Slide

  37. What Do Namespaces Apply to ?
     Functions
     Classes
     Traits
     Interfaces
     Constants declared
    with const keyword
     Variables
     Constants declared
    with define()
     Non-PHP native
    constructs:
    - hook names

    View Slide

  38. How Does it Work ?
    Namespace
    always applied
    • Classes
    • Traits
    • Interfaces
    Fallback to global
    namespace
    • Functions
    • Constants
    Namespace
    irrelevant
    • Magic
    Constants

    View Slide

  39. FQN:
    Fully\Qualified\Name
    \Fully\Qualified\Name

    View Slide

  40. How Does it Work ?
    Namespace
    always applied
    • Classes
    • Traits
    • Interfaces
    Fallback to global
    namespace
    • Functions
    • Constants
    Namespace
    irrelevant
    • Magic
    Constants
    Must use FQN or
    use statement
    May use FQN or
    use statement
    N/A

    View Slide

  41. Namespaces
    class NSExample extends Base_Example {
    public function do_something( $input ) {
    return str_pad( $input, 10, '-', STR_PAD_LEFT );
    }
    }
    $ns_example = new NSExample();

    View Slide

  42. Namespaces
    namespace MyNS;
    class NSExample extends Base_Example {
    public function do_something( $input ) {
    return str_pad( $input, 10, '-', STR_PAD_LEFT );
    }
    }
    $ns_example = new NSExample();

    View Slide

  43. Namespaces
    namespace MyNS;
    class NSExample extends \Base_Example {
    public function do_something( $input ) {
    return \str_pad( $input, 10, '-', \STR_PAD_LEFT );
    }
    }
    $ns_example = new NSExample();

    View Slide

  44. Import Use Statements
    namespace MyNS;
    use Base\Example;
    use function str_pad;
    use const STR_PAD_LEFT;
    class NSExample extends Example {
    public function do_something( $input ) {
    return str_pad( $input, 10, '-', STR_PAD_LEFT );
    }
    }
    $ns_example = new NSExample();
    5.3
    5.6

    View Slide

  45. PHP 7 Opcode Cached Functions
     is_null()
     is_bool()
     is_long()
     is_int()
     is_integer()
     is_float()
     is_real()
     is_string()
     is_array()
     is_object()
     is_resource()
     assert()
     strlen()
     defined()
     call_user_func()
     call_user_func_array()
     boolval()
     intval()
     floatval()
     doubleval()
     strval()
     chr()
     ord()
     in_array()
     count()
     get_class()
     get_called_class()
     gettype()
     func_num_args()
     func_get_args()
     array_slice()
     sizeof()
     array_key_exists()
    7.2
    7.1
    7.4
    7.0

    View Slide

  46. Type Declarations
    5.0, 5.4, 7.0 – 7.2
    Sgarton

    View Slide

  47. Type Declarations
     5.0: Parameter Type
    Declarations
     7.0: Return Type
    Declarations
     7.0: Strict Types
     7.1: Nullable Types
    5.0 Class/Interface name based
    5.1 array
    5.2 self
    parent
    5.4 callable
    7.0 bool, int, float, string
    7.1 iterable, void
    7.2 object

    View Slide

  48. Type Declarations
    function get_tax_posts( $taxonomies = null, $limit = 5) {
    _deprecated_function( __FUNCTION__, '5.x', 'wp_get_tax_posts' );
    $taxonomies = (array) $taxonomies;
    $limit = (int) $limit;
    ...
    return $post_data;
    }
    function wp_get_tax_posts( ?array $taxonomies = null, int $limit = 5)
    : array {
    ...
    return $post_data;
    }
    return wp_get_tax_posts( $taxonomies, $limit );

    View Slide

  49. But.... There is so Much More !
    Finally
    Garbage
    Collector
    Nested
    Exceptions
    Closures
    Goto
    Late Static
    Binding
    OpCache
    Nowdocs

    View Slide

  50. And Then There's PHP 7....
    Expectations
    with assert()
    Unicode
    Escapes
    Group Use
    Declarations
    More
    Exception
    Types
    More
    Catchable
    Errors
    Uniform
    Variable
    Syntax
    Null
    Coalesce
    (equals)
    Scalar Type
    Hints & Return
    Type Hints

    View Slide

  51. And Yet More 7.x Goodies!
    Spread in
    arrays
    Multi
    catch
    Parameter
    type
    widening
    Short lists,
    keyed lists
    iterable,
    object & void
    types
    Nullable
    types
    Exceptions
    on Fatals
    Class
    constant
    visibility

    View Slide

  52. Keep
    Educating
    Yourself

    View Slide

  53. Thanks!
    Any
    questions ?
    Slides: https://speakerdeck.com/jrf
    Feedback: https://joind.in/talk/dafa1
    @jrf_nl @jrfnl @jrf

    View Slide