Cutting-Edge PHP

UMN Code-People: November 7, 2013

David Naughton: UMN Libraries Web Development

@nihiliad

Who Cares?

PHP Sucks

What about your Favorite Language?

“There are only two kinds of programming languages: those people always bitch about and those nobody uses.”

Bjarne Stroustrup

"What are five things you hate about your favorite language?"

“If someone can't find five things to hate about his favorite tool, he doesn't know it well enough to either advocate it or pull in the big dollars using it. He hasn't used it in enough different situations to fully explore it. He's advocating it as a culture or religion, which means that if I don't choose his favorite technology, I'm wrong.”

brian d foy

"PHP Sucks! But I Like It!"

“I actually agree with the majority of what he said in his post [PHP: a fractal of bad design]. PHP is inconsistent. It is verbose. It does have a lot of weird behavior. It does have a lot of problems. It can be ugly. It can be really awkward to work around. It can leave a lot to be desired... But it's also incredibly powerful.”

Anthony Ferrara

"PHP is much better than you think"

“PHP is probably not the best language out there, and I'm the first one to scream about its quirks, but PHP is the best web platform... ever.”

Fabien Potencier

Not sure I agree with that last phrase, but the title is accurate for most of us.

PHP History

Core Language

PHP History

Reusable Components

PEAR Logo

SUCKS

PEAR Sucks

High Entry Barriers

  • Draconion contribution standards enforced by a central committee.
    • Few contributions to pear.php.net.
    • Multiple, decentralized PEAR "channels".
    • Can't find anything.
  • Originally built for system-wide installs, requiring root.
  • Complex, poorly-documented system.

PEAR Sucks

Package Counts

CPAN127,119
RubyGems65,484
npm46,451
PyPI36,377
PEAR595

Composer

Composer Logo

http://getcomposer.org

Composer

“I'd say until early 2012 it was pretty unusable, yet people used it. I guess that's how badly it was needed.”

Jordi Boggiano, Composer Co-Creator

Composer

Packages/versions over time

Graph of Composer Packages/Versions Over Time

packagist.org: 18,500 packages.

Almost doubled since April!

Composer

Simpler and Easier

  • Low entry barriers to publishing on packagist.org.
  • Per-app package sets, similar to Ruby Bundler.
  • Simple JSON package metadata format, inspired by node.js npm.

Composer Quick Start

After installing Composer...


$ cd app-package-dir/
$ vi composer.json
          

Declare a dependency:


{
  "require": {
    "guzzle/guzzle": "v3.7.4"
  }
}
          

Install it:


$ composer install
          

Using Composer-Installed Packages

Composer automatically generates a PSR-0-compliant autoloader.


require 'app-package-dir/vendor/autoload.php';

$client = new \Guzzle\Http\Client('http://guzzlephp.org');
$request = $client->get('/');
$response = $request->send();
          

Composer and github.umn.edu


{
  "require": {
    "umnlib/config": "*"
  },
  "repositories": [
    {
      "type": "vcs",
      "url": "git@github.umn.edu:Libraries/config-php.git"
    }   
  ]   
}
          

(Composer can search multiple repository types for packages: packagist.org, github, PEAR...)

Who Cares?

“PHP sucks at sharing... Sharing is how open source works. Sucking at sharing is how open source dies.”

— Larry Garfield

Drupal core contributor, Drupal 8 Web Services Lead, Senior Architecht and Consultant at Palantir.net

Composer: There's a Module (or Library) for That

DrupalCon Portland 2013

FIG

PHP Framework Interop Group

PHP Standard Requests, e.g. PSR-0

Drupal, Symfony, almost all major projects participate.

PHP Community and Ecosystem

Symfony

Testing

  • PHPUnit, now available via Composer!
  • Behavior-Driven Development
  • Mockery mock object framework can be integrated with PHPUnit or PHPSpec.
  • Prophecy, a highly-opinionated, very powerful and flexible mocking framework. Integrated with PHPSpec, can be used with PHPUnit.

DocBlocks with PHPDoc

phpDocumentor has won, set the PHPDoc standard, and is now available via Composer!


/**
 * Short description.
 *
 * Long description. This text may contain
 * multiple lines and even some _markdown_.
 *
 * * Markdown style lists function too
 * * Just try this out once
 *
 * @param int    $example  Example function/method parameter description.
 * @param string $example2 Second example.
 */
          

Annotations

Define your own DocBlock annotations with the Doctrine ORM's annotations component:


namespace MyProject\Entities;

use Doctrine\ORM\Mapping AS ORM;
use Symfony\Component\Validation\Constraints AS Assert;

/**
 * @ORM\Entity
 * @MyProject\Annotations\Foobarable
 */
class User {}
          

PHP Core Language

Metaprogramming

Lambdas

...or anonymous functions, introduced in 5.3:


$input = array(1, 2, 3, 4, 5);
$output = array_filter($input, function ($v) { return $v > 2; });

// or...

$max_comparator = function ($v) { return $v > 2; };
$output = array_filter($input, $max_comparator);
          

Don't use create_function!


$max_comparator = create_function('$v', 'return $v > 2;');
          

Closures

Lamdbas with state, i.e. anonymous functions that are "closed over" variables from the surrounding scope:


$x = 1;
$incrementor = function() use (&$x) { return ++$x; }
$incrementor(); // 2
$incrementor(); // 3
$incrementor(); // 4
          

Functional Programming

Lambdas and closures allow functional programming, even the infamous Y-Combinator:


function Y($F)
{
  $func = function ($f) { return $f($f); };
 
  return $func(function ($f) use($F)
  {
    return $F(function ($x) use($f)
    {
      $ff = $f($f);
 
      return $ff($x);
    });
  });
}
          

Traits

New in 5.4, traits provide OO reuse without inheritance, like interfaces, but with implementation:


class Base {
    public function sayHello() { echo 'Hello '; }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base { use SayWorld; }
$o = new MyHelloWorld();
$o->sayHello(); // Hello World!
          

For the theory, see Traits - Composable Units of Behavior.

Generators

New in 5.5, generators allow for very simple and easy implementation of iterators:


function fibonacci() {
  $last = 0;
  yield 0;
  $current = 1;
  yield 1;
  while (true) {
    $current = $last + $current;
    $last = $current - $last;
    yield $current;
  }
}

// Prints the first sixteen Fibonacci numbers:
foreach (fibonacci() as $n => $Fn) {
  echo "F[$n] = $Fn\n";
  if ($n == 15) break; // Prevent an infinite loop!
}
          

Generators are Iterators

An equivalent way to generate the Fibonacci numbers, by calling methods from the Iterator interface, which Generator implements:


$generator = fibonacci();
$reflector = new ReflectionClass($generator);
$reflector->getName(); // Generator
$reflector->getInterfaceNames(); // Iterator, Traversable

while ($generator->valid()) {
  $n = $generator->key();
  $Fn = $generator->current();
  echo "F[$n] = $Fn\n";
  if ($n == $limit) break; // Prevent an infinite loop!
  $generator->next();
}
          

Further Reading

PHP: The Right Way

Thank You!