PHP in the year++

Get with the program: PHP 5.3 and beyond!

Mats Lindh / @matslindh

4. Desember 2013, TechShock

About me

Does search on Solr and Lucene, PHP and python for Amedia.

Just passed 15 years as a PHP developer (since PHP 3.0.3-ish).

Let's all go to the features!

Namespaces (5.3)

"The Battle of the Separators"


<?php
namespace foo;
class Bar {} // foo\Bar

<?php
require "foo.php";

use foo as baz;
$o = new baz\Bar();

Late Static Binding (5.3)

(and dynamic access to static methods)


<?php
class A {
    public static function who() { echo __CLASS__; }
                
    public static function test() {
        self::who(); static::who();
    }
}
                                        
class B extends A {
    public static function who() { echo __CLASS__; }
}
                                                        
B::test(); // AB

$a = "foo";
$a::factory();

Closures (5.3)

Makes functions first class members

$foo = function ($a) {
    return $a*2;
}

$foo(8); // 16
$var = 32;

$foo = function ($a) use ($var)
{
    return $a * $var;
}

$foo(8); // 256

Cycle-detecting Garbage Collector (5.3)

Fixes potential memory leaks with arrays containing other arrays, etc.

php-fpm (5.3)

"The PHP FastCGI Process Manager"

The weapon of choice for PHP on nginx in particular. Spawns a pool of FastCGI workers / processes that handles requests as they come in.

Traits - Horizontal Composition (5.4)

"Compiler Assisted Copy'n'paste"

<?php
trait HelloWorlder {
    function hello() { echo "Hello World!\n"; }
}

class Welcomer {
    use HelloWorlder;
}

(new Welcomer())->hello();

Short Array Syntax (5.4)

<?php
$a = ['foo', 'bar', 'baz'];
$d = ['foo' => 'bar', 'baz' => 'eggs'];

Function&Array Dereferencing (5.4)

<?php
function foo() {
    return array('bar', 'baz', 'eggs', 'spam');
}

echo foo()[2]; // eggs
echo array('foo', 'bar', 'baz')[0]; // foo
echo ['foo', 'bar'][1]; // bar

<?= Available At Any Time (5.4)

"Using PHP as an actual templating language? In all my days.."

<?= $foo ?> // <?php echo $foo; ?>

Built in CLI Web Server for Development and Testing (5.4)

php -S localhost:8000 -t foo/ router.php
<?php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
    return false;    // serve the requested resource as-is.
}

echo "Insert default value here.";

Callable as a Typehint (PHP 5.4)

<?php
class A {
    static public function bar() {}
    public function baz() {}
}
function spam() {}
function foo(Callable $foo) { $foo(); }

foo(array("A", "bar")); // works
foo([new A(), "baz"]); // works
foo("spam"); // works
foo(function () {}); // works
foo(14); // fatal error
foo("eggs"); // fatal error

A Native Password Library (5.5)

"Hash it like it's 1999"

Provides secure password hashing using BCRYPT and proper salting by default.

$hash = password_hash($password, PASSWORD_BCRYPT);
if (password_verify($password, $hash)) {

Use   password_compat   on PHP < 5.5.

Generators (5.5)

"Give it to me baby, a-ha, a-ha"

<?php
function square($value) {
    while (true) {
        $value *= 2;
        yield $value;
    }
}

foreach (square(2) as $val) {
    if ($val > 256) break;

    var_dump($val); // 4 8 16 32 64 128 256
}

Native opcache Extension Bundled (5.5)

"Zend Optimiser+ gets used!"

APC more or less dead; use APCu for in-memory cache if needed.

Resolve class name with ::class (5.5)

<?php
namespace foo;
class A {}

echo A::CLASS; // foo\A

All the small things

  • Shorthand Ternary Operator (?:) (5.3)
    $foo ?: "default";
  • New magic methods (5.3)
    __callStatic(), __invoke()
  • Callable as a typehint (5.4)
    array('ClassName', 'Foo'), $closure, [$obj, 'method']

More the small things

  • finally (try/catch/finally) (5.5)
  • empty() with arbitary expressions (5.5)
    if (empty(trim($foo))) // if (trim($foo))
  • list() support in foreach() (5.5)
    foreach ($arr as list($el1, $el2))
  • JsonSerializable (5.5)
  • mysqlnd used by default (5.5)
  • Binary notation (0b101.0b101)

Let's get standardized

PSR-0: Autoloading done mostly right

A common protocol for how to map class names to actual file paths.


spl_autoload_register(function($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
                                                
    require $fileName;
});

PSR-(1|2)

Common coding standards across frameworks.

Replaces the old PEAR coding standards / Zend / etc.

PSR-3

Logging interface

PSR-4: Eh, forget the last one about autoloading

Small changes to avoid a namespaced class mapping to the same file as a class name with _ as separators.

Foo\Bar\Baz vs Foo_Bar_Baz

Shorter path mapping, more suitable for composer-style distribution.

vendor/foo/bar/src/Baz

.. which leads us into ..

Questions?

.. and possibly answers?

Get in touch!

Mats Lindh

Amedia Salg og Marked AS

mats@lindh.no · @matslindh · LinkedIn · Stack Overflow

€kN€kd€kd€kd;:q€kbq!