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

PHP in 2017

PHP in 2017

Originally presented at the PHP Adelaide meetup in May 2017, this talk aims to serve as a very high-level overview of concepts, groups, and methodologies modern PHP developers should be considering.

It covers common practices, the Framework Interoperability Group, PHP Standard Recommendations, design patterns, and good practices to follow in the modern web environment.

Michael Dyrynda

May 18, 2017
Tweet

More Decks by Michael Dyrynda

Other Decks in Programming

Transcript

  1. Keep up to date • PHP development moves much quicker

    than it used to • HHVM kicked PHP development into gear • Largely rewritten engine == much faster • PHP 5.6 won't receive updates beyond 2018
  2. Keep up to date - release cycles The PHP Group

    implemented a release timeline for new versions in 2011 • at least one (patch) release every month • a minor release should occur once a year • every minor release is actively supported for at least 2 years • active support followed by 1 year of security/bug fixes
  3. PHP Framework Interoperability Group (FIG) • Formed by members of

    major frameworks in 2009 • Discuss commonality between projects to work together • Main audience is each other, but many in the wider community adopt decisions • Discuss, vote, and implement PHP Standard Recommendations (PSRs)
  4. PHP Standard Recommendations (PSRs) Most well-known recommendations • PSR-0 -

    Original autoloading standard • PSR-1 - Basic coding standard • PSR-2 - Coding style guard • PSR-4 - Autoloading standard
  5. Autoloading standards - PSR-0 PSR-0 class naming and autoloading came

    from Horde/PEAR conventions before PHP supported namespaces (PHP < 5.3). /path/to/src Dyrynda/ ServiceA/ ClassA.php # Dyrynda_ServiceA_ClassA Skinner/ ServiceB/ ClassB.php # Skinner_ServiceB_ClassB
  6. Autoloading standards - PSR-4 PSR-4 meant packages were no longer

    in a single, global location vendor/ dyrynda/ package_a/ src/ ClassA.php # Dyrynda\PackageA\ClassA tests/ package_b/ src/ ClassB.php # Dyrynda\PackageB\ClassB
  7. PSR-0 and PSR-4 - autoloading standards Each package must have

    at least a top-level vendor namespace and a package-level namespace Dyrynda\PhpAdelaide\ModernPhp | | | Vendor Package Class
  8. PSR-1 and PSR-2 - coding (style) standards Cover many things

    about what code looks like • Which <?php ?> tags should be used • Whether or not we should be using tabs or spaces • You don't have to follow these but it helps
  9. PHP the language Flexible, dynamic, and lets developers writing PHP

    how they want to. • Object-oriented programming in PHP 5 (2004) • Anonymous functions, namespaces in PHP 5.3 (2009) • Traits in PHP 5.4 (2012)
  10. Object-oriented programming class Profile { private $name; private $twitter; public

    function __construct($name, $twitter) { $this->name = $name; $this->twitter = $twitter; } public function getName() { return $this->name; } public function getTwitter() { return $this->twitter; } }
  11. Functional programming array_map(function ($n) { return $n * 2; },

    [1, 2, 3]); // [2, 4, 6] array_filter(['Michael', '', 'Dyrynda'], function ($string) { return trim($string) !== ''; }); // ['Michael', 'Dyrynda']
  12. Meta programming class Profile { private $attributes; public function __get($key)

    { return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null; } public function __set($key, $value) { $this->attributes[$key] = $value; } public function __toString() { return "{$this->name} - {$this->twitter}"; } } $profile = new Profile; $profile->name = 'Michael Dyrynda'; $profile->twitter = '@michaeldyrynda'; print $profile->name; // Michael Dyrynda print $profile->twitter; // @michaeldyrynda print $profile->instagram; // null print $profile; // Michael Dyrynda - @michaeldyrynda
  13. Namespaces • Allows the same class to exist multiple times

    in a project • Available since PHP 5.3 • The backbone of the PSR-4 autoloading standard
  14. Standard PHP Library (SPL) • Native classes and interfaces for

    you to use and extend • Predefined constants, common data structures, and iterators for traversing them • Interfaces (for iterators) and Exceptions • File handling
  15. Dependency management • The main charter of the FIG is

    on interoperability of code • Code is distributed via packages, primarily on Packagist • Packages are installed using Composer • No more copy/paste from phpclasses.org • Composer is specifically for managing dependencies and configuring autoloading
  16. Installing packages composer require psr/log • Adds the dependency to

    your composer.json file, as well as an entry to your composer.lock file. • composer.json describes your project dependencies • composer.lock is for installing your dependencies • Downloads and installs the package to vendor/psr/log • Automatically sets up autoloading in vendor/autoload.php
  17. Date and time • Dates and times are hard •

    DateTime and DateTimeImmutable classes make life easier • DateTimeZone, DateInterval, and DatePeriod complement them • Carbon makes life even easier, with terse method names
  18. Date and time // DateTime $date = new DateTime('now', new

    DateTimeZone('Australia/Adelaide')); $date->add(new DateInterval('P1D')); // Add one day print $date->format('Y-m-d H:i:s'); // $date is now +1 day from now // DateTime method for brevity print (new DateTime('now', new DateTimeZone('Australia/Adelaide'))) ->add(new DateInterval('P1D')) ->format('Y-m-d H:i:s'); // Using Carbon - more readable print Carbon::now('Australia/Adelaide')->addDay()->format('Y-m-d H:i:s');
  19. (Common) design patterns • Factories • Singletons • Strategy •

    Front controller • Model-View-Controller (MVC)
  20. Dependency injection Dependency injection is a software design pattern that

    allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time. — Wikipedia
  21. Without dependency injection class UserController { private $repo; public function

    __construct() { $this->repo = new UserRepository; } }
  22. With dependency injection class UserController { private $repo; public function

    __construct(UserRepository $repo) { $this->repo = $repo; } }
  23. Databases • ! mysql • mysqli - MySQL-improved, simple transition

    from mysql • Swapped args from ($query, $link) to ($link, $query) • PDO - common interface for different persistence layers • ⚠ Does not translate your queries • Framework abstractions - Doctrine, ActiveRecord, etc.
  24. Templating • PHP is a templating language • Templates are

    a convenient way of separating controller, domain, and presentation logic (MVC) • Clear separation between presentation and the rest of your app • Improve organisation of presentation code, often in a views/ folder
  25. Templating - plain PHP • Natural choice for many, given

    they are just PHP • Easy to intermingle PHP code - just not domain logic ! • No new syntax to learn • Beware of escaping issues - never trust your user input
  26. Templating - plain PHP // Danger <?= $user['bio'] ?> //

    <script>javascript:alert('Hello, world!');</script> // Safety <?= htmlspecialchars($user['bio']) ?> // &lt;script&gt;javascript:alert('Hello, world!');&lt;/script&gt;
  27. Templating - compiled • PHP's improved as a language, not

    so much for templating • Compiled options like Twig and Smarty fill the void • Offer new syntax specific to templating • Automatic escaping, inheritance, simplified control structures, etc. • Designed to be easier to write, cleaner to read, safer to use • Many frameworks have their own flavour (Aura.View, Blade)
  28. Errors • PHP is typically exception-light • Many errors will

    emit, but not stop code flow unless fatal • PHP has several levels of error severity - errors, notices, warnings, etc. • E_STRICT and E_DEPRECATED were introduced to suggest changes in code to ensure better forward-compatibility
  29. Changing error behaviour • You can override which errors PHP

    displays - useful in production, as long as you log them somewhere error_reporting(E_ERROR | E_WARNING); • You can even suppress errors inline print @$foo['bar']; • PHP's error control operator will completely swallow this error.
  30. Changing error behaviour ! If you can avoid using the

    suppression operator, you should consider it. // Avoid print @$foo['bar']; // PHP < 7.0 print isset($foo['bar']) ? $foo['bar'] : ''; // PHP >= 7.0 print $foo['bar'] ?? '';
  31. Changing error behaviour It is default practice in Symfony and

    Laravel to translate any PHP errors into ErrorExceptions
  32. Exceptions • Common in most popular programming languages • Often

    overlooked in PHP • Error makes it impossible for anybody to handle them • Exceptions ought to be thrown to make developers aware of an error
  33. SPL Exceptions • You can create dedicated exception classes of

    your own, extending the base Exception class • PHP has many specific exception classes • InvalidArgumentException • LogicException • RuntimeException • http://php.net/spl.exceptions for a comprehensive list
  34. Passwords • Don't roll your own password security • Don't

    roll your own password security • Don't use md5, sha1 - these are reproducible and susceptible to collision • Passwords are automatically salted since PHP 7.0, adding a random string to each password before hashing, using built- in functions
  35. Passwords Hashing functions have been available since 5.5 $hash =

    password_hash('secret', PASSWORD_DEFAULT); if (password_verify('forgetful', $hash)) { // Login ok } else { // Forgetful user. Or hacker! }
  36. Passwords - rehashing A mechanism exists to determine if a

    hashed value needs rehashing. if (password_verify('secret', $hash)) { if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) { // If so, create new hash and replace old one $newHash = password_hash($password, PASSWORD_DEFAULT, $options); } // Login }
  37. Filtering • Never trust foreign content. Ever. • $_GET, $_POST,

    $_SERVER can be user-manipulated • Files, session, cookies, etc. are all foreign content • filter_var and filter_input can be used for filtering • You should filter all input, and sanitise (escape) on output • Frameworks will usually handle this for you !
  38. Thank you • Michael Dyrynda - @michaeldyrynda • North Meets

    South Web Podcast - @northsouthaudio • Laravel News Podcast - @laravelnews