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 full-size slide

  2. Olivier Gobet

    View full-size slide

  3. PHP Supported Versions

    View full-size 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 full-size slide

  5. Let's
    Modernize
    All The Things!!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. EricBerthe 
    kconnors 

    View full-size slide

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

    View full-size slide

  10. Let's Rewrite from
    Scratch!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. 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 full-size slide

  16. Clean Up
    (code-level)

    View full-size slide

  17. 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 full-size slide

  18. Use case-insensitive
    searches.

    View full-size slide

  19. 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 full-size slide

  20. 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 full-size slide

  21. Clean Up
    (application-level)

    View full-size slide

  22. 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 full-size slide

  23. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  31. 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 full-size slide

  32. Namespaces
    Seemann
    5.3

    View full-size slide

  33. Logical Grouping
    of Code

    View full-size slide

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

    View full-size slide

  35. 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 full-size slide

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

    View full-size slide

  37. FQN:
    Fully\Qualified\Name
    \Fully\Qualified\Name

    View full-size slide

  38. 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 full-size slide

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

    View full-size slide

  40. 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 full-size slide

  41. 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 full-size slide

  42. 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 full-size slide

  43. 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 full-size slide

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

    View full-size slide

  45. 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 full-size slide

  46. 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 full-size slide

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

    View full-size slide

  48. 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 full-size slide

  49. 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 full-size slide

  50. Keep
    Educating
    Yourself

    View full-size slide

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

    View full-size slide