Modern PHP
Charles Anderson

Hack Salem! - July 2019
TL;DR
• PHP has grown a lot over the last 15 - 20 years

• duh!

• It’s much more reasonable for larger projects
Me
• I’m a systems programmer -
code w/o a face

• I am not really a PHP
programmer

• Ruby, Puppet, bash, etc.

• I did some PHP back in the
early Naughties

• CGI and bare Servlets before
that Gorak aka Steve aka Larry
Acquia
• Acquia provides enterprise-grade Drupal CMS hosting

• Lots more, too

• Operate a fleet of tens of thousands of AWS servers

• Controlled with a mix of PHP, Ruby, Puppet, etc.

• Acquia is hiring
PHP 4 and Before
• PHP started as a simple way to add some computation to
web pages

• The simplest (lamest) example was a visitor counter
Gotta Have a Counter
<!DOCTYPE html>
<html>
<body>
<h1>My first PHP page</h1>
<p>Hello world</p>
<?php
$path = './counter.txt';
$file = fopen($path, 'r');
$count = fgets($file, 1000);
fclose($file);
$count = abs(intval($count)) + 1;
?>
<p>Congratulations: you are visitor
number:
<b> <?php echo "{$count}n"; ?> </b>
</p>
<?php
$file = fopen($path, 'w');
fwrite($file, $count);
fclose($file);
?>
</body>
</html>
HTML
HTML
PHP Business Logic
HTML
PHP Presentation Logic
PHP Business Logic
PHP
• A simple mix of HTML and business logic - what could
possibly go wrong?

• Global functions and variables (unless local in a function)
Global Libraries
PHP Language
• Variables - $name
• Dynamic typing: $name=‘Damien’; $name=666;

• Scalar types: boolean, integer, double, string

• Arrays: always hashes - array[1] or array[‘name’]

• Flow control: if, switch, for, foreach, while

• Including code: include or require
Classes
• PHP 4 added classes

• Methods and properties - all public

• $object->method() or $object->property

• Single inheritance with extends keyword

• Introspection - classes, methods, properties, parent class

• Example: PEAR database library to abstract underlying
DB
PHP 7.2
Objects and Classes
• Visibility - public, protected, private

• Interfaces - a list of methods that must be implemented

• Abstract classes - implement a subset of methods of an
interface

• Traits - a collection of method implementations to include
in a class without inheritance - mix-ins

• Basically, the kitchen sink
Visibility
class Politician {
public function promises() {}
protected function donors() {}
private function scandals() {}
private $slushFundBalance = 1000000;
}
Interfaces
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
Abstract Classes
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// no getHtml method - must be abstract
abstract class SetTemplate implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
Traits
trait Logger {
function log($msg) {
echo '(' . __CLASS__ .  ') ' . $msg ;
}
}
class BankAccount {
use Logger;
function withdraw($amount) {
$this->log('withdraw ' . $amount);
}
...
}
class Database {
use Logger;
function query($sql) {
$this->log('query ' .$sql);
}
...
}
Type Hints
• Have the option (not required) to specify types on
parameters, properties, and return values

• If a type is specified, you must (strictly) abide

• Nullable types - e.g., a function could return Foo or NULL

• Variables can still be dynamically typed

• Provides a path to slowly introduce typing to an existing
body of software
Type Hints
function sum(int $a, int $b) {
return $a + $b;
}
$result = sum(3, 4); // OK
$result = sum(3, 'cats') //FAIL
$result = sum(3.5, 4); // OK - really?
// another file
declare(strict_types=1);
$result = sum(3.5, 4); // FAIL
Nullabe Types
function welcome(?string $name) {
echo $name;
}
welcome('world'); // OK
welcome(null); // OK
welcome(); // FAIL
function welcome($name): ?string
{
return null; // OK
}
function welcome($name): ?string
{
return 'Welcome ' . $name; // OK
}
function welcome($name): ?string
{
return 33; // FAIL
}
Large Scale Software
• Namespaces - no longer only a global, flat namespace

• Packaging / Composer: install libraries and manage
dependencies
Namespaces
<?php
namespace MyApplication;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
<?php
namespace ThirdPartyDatabaseUtil;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
$status = CONNECT_OK; // local namespace
$status = MyApplicationCONNECT_OK; // other namespace
Top-Level Namespace
Sub-Namespace
Packages
• PHP code can be packaged into a reusable collection
called simply a package - c.f., Ruby gems

• The Composer tool is a per-project package manager that
fetches the packages you need and all of the
dependencies - c.f., Ruby Bundler
Composer
• In your project directory, you can run

composer require "twig/twig:^2.0"

• Creates composer.json and composer.lock files and
vendor directory

• composer install - install all the packages

• To use the packages, include one line of code:

require_once __DIR__ . ‘/vendor/autoload.php';
• Auto-loading loads all the packages at runtime
Other Items
• Exceptions - code without checking return values

• Testing frameworks - phpUnit and Behat (BDD)

• Style/lint checkers - phpstan and phpcs 

• see also John’s talk
Conclusions
• PHP has grown up a lot in the last 15 years - definitely no
longer Stone Age

• You can easily write large, well structured applications

• You can still write a mess of logic and presentation - it’s
a free country

Modern php

  • 1.
  • 2.
    TL;DR • PHP hasgrown a lot over the last 15 - 20 years • duh! • It’s much more reasonable for larger projects
  • 3.
    Me • I’m asystems programmer - code w/o a face • I am not really a PHP programmer • Ruby, Puppet, bash, etc. • I did some PHP back in the early Naughties • CGI and bare Servlets before that Gorak aka Steve aka Larry
  • 5.
    Acquia • Acquia providesenterprise-grade Drupal CMS hosting • Lots more, too • Operate a fleet of tens of thousands of AWS servers • Controlled with a mix of PHP, Ruby, Puppet, etc. • Acquia is hiring
  • 6.
    PHP 4 andBefore • PHP started as a simple way to add some computation to web pages • The simplest (lamest) example was a visitor counter
  • 7.
    Gotta Have aCounter <!DOCTYPE html> <html> <body> <h1>My first PHP page</h1> <p>Hello world</p> <?php $path = './counter.txt'; $file = fopen($path, 'r'); $count = fgets($file, 1000); fclose($file); $count = abs(intval($count)) + 1; ?> <p>Congratulations: you are visitor number: <b> <?php echo "{$count}n"; ?> </b> </p> <?php $file = fopen($path, 'w'); fwrite($file, $count); fclose($file); ?> </body> </html> HTML HTML PHP Business Logic HTML PHP Presentation Logic PHP Business Logic
  • 8.
    PHP • A simplemix of HTML and business logic - what could possibly go wrong? • Global functions and variables (unless local in a function)
  • 9.
  • 10.
    PHP Language • Variables- $name • Dynamic typing: $name=‘Damien’; $name=666; • Scalar types: boolean, integer, double, string • Arrays: always hashes - array[1] or array[‘name’] • Flow control: if, switch, for, foreach, while • Including code: include or require
  • 11.
    Classes • PHP 4added classes • Methods and properties - all public • $object->method() or $object->property • Single inheritance with extends keyword • Introspection - classes, methods, properties, parent class • Example: PEAR database library to abstract underlying DB
  • 12.
  • 13.
    Objects and Classes •Visibility - public, protected, private • Interfaces - a list of methods that must be implemented • Abstract classes - implement a subset of methods of an interface • Traits - a collection of method implementations to include in a class without inheritance - mix-ins • Basically, the kitchen sink
  • 14.
    Visibility class Politician { publicfunction promises() {} protected function donors() {} private function scandals() {} private $slushFundBalance = 1000000; }
  • 15.
    Interfaces interface iTemplate { public functionsetVariable($name, $var); public function getHtml($template); } class Template implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } }
  • 16.
    Abstract Classes interface iTemplate { publicfunction setVariable($name, $var); public function getHtml($template); } // no getHtml method - must be abstract abstract class SetTemplate implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } }
  • 17.
    Traits trait Logger { functionlog($msg) { echo '(' . __CLASS__ .  ') ' . $msg ; } } class BankAccount { use Logger; function withdraw($amount) { $this->log('withdraw ' . $amount); } ... } class Database { use Logger; function query($sql) { $this->log('query ' .$sql); } ... }
  • 18.
    Type Hints • Havethe option (not required) to specify types on parameters, properties, and return values • If a type is specified, you must (strictly) abide • Nullable types - e.g., a function could return Foo or NULL • Variables can still be dynamically typed • Provides a path to slowly introduce typing to an existing body of software
  • 19.
    Type Hints function sum(int$a, int $b) { return $a + $b; } $result = sum(3, 4); // OK $result = sum(3, 'cats') //FAIL $result = sum(3.5, 4); // OK - really? // another file declare(strict_types=1); $result = sum(3.5, 4); // FAIL
  • 20.
    Nullabe Types function welcome(?string$name) { echo $name; } welcome('world'); // OK welcome(null); // OK welcome(); // FAIL function welcome($name): ?string { return null; // OK } function welcome($name): ?string { return 'Welcome ' . $name; // OK } function welcome($name): ?string { return 33; // FAIL }
  • 21.
    Large Scale Software •Namespaces - no longer only a global, flat namespace • Packaging / Composer: install libraries and manage dependencies
  • 22.
    Namespaces <?php namespace MyApplication; const CONNECT_OK= 1; class Connection { /* ... */ } function connect() { /* ... */ } <?php namespace ThirdPartyDatabaseUtil; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } $status = CONNECT_OK; // local namespace $status = MyApplicationCONNECT_OK; // other namespace Top-Level Namespace Sub-Namespace
  • 23.
    Packages • PHP codecan be packaged into a reusable collection called simply a package - c.f., Ruby gems • The Composer tool is a per-project package manager that fetches the packages you need and all of the dependencies - c.f., Ruby Bundler
  • 24.
    Composer • In yourproject directory, you can run
 composer require "twig/twig:^2.0" • Creates composer.json and composer.lock files and vendor directory • composer install - install all the packages • To use the packages, include one line of code:
 require_once __DIR__ . ‘/vendor/autoload.php'; • Auto-loading loads all the packages at runtime
  • 25.
    Other Items • Exceptions- code without checking return values • Testing frameworks - phpUnit and Behat (BDD) • Style/lint checkers - phpstan and phpcs • see also John’s talk
  • 26.
    Conclusions • PHP hasgrown up a lot in the last 15 years - definitely no longer Stone Age • You can easily write large, well structured applications • You can still write a mess of logic and presentation - it’s a free country