PHP 5.4

Dorian Sarnowski
April 14, 2012

PHP 5.4? Why not 6.0?

New features (syntactic sugar actually)

Class member access on instantiation

class Thumbnailer {
    public static function factory() {
        return new self;
    }

    public function doSomeWeirdStuff() {}
}

// PHP 5.3
Thumbnailer::factory()->doSomeWeirdStuff();
// PHP 5.4 (method factory() isn't needed anymore)
(new Thumbnailer())->doSomeWeirdStuff();

Short array syntax

// PHP 5.3
$speakers = array(
    'Dorian Sarnowski',
    'Benedykt Dryl',
    'Andrzej Borkowski',
    'Grzegorz Nowicki'
);
// PHP 5.4
$speakers = [
    'Dorian Sarnowski',
    'Benedykt Dryl',
    'Andrzej Borkowski',
    'Grzegorz Nowicki'
];

Function array dereferencing

function getSpeakers() {
    return [
        'Dorian Sarnowski', 'Benedykt Dryl', 
        'Andrzej Borkowski', 'Grzegorz Nowicki'
    ];
}
// PHP 5.3
$speakers = getSpeakers();
$currentSpeaker = $speakers[0];
// PHP 5.4
$currentSpeaker = getSpeakers()[0];

<?= is now always available

<ul>
    <?php foreach ($this->speakers as $speaker) : ?>
        <li>
            <?php echo $speaker ?>
            <?= $speaker ?>
        <li>
    <?php endforeach ?>
</ul>

Now, this one works everywhere, regardless of the short_open_tag option in php.ini.

Binary number format

echo 123    // 123
echo 0x123; // 291
echo 0123;  // 83
// PHP 5.3
echo bindec('110'); // 6
// PHP 5.4
echo 0b110;         // 6

JsonSerializable interface

class Data implements JsonSerializable{

    public function jsonSerialize() {
        return ['what' => 'meet.php', 'when' => 'today'];
    }

};

$data = new Data;
echo json_encode($data);

How long did your script take to execute?

$_SERVER['REQUEST_TIME_FLOAT'];

Callable Typehint

function test(callable $x) {}

New features (the real ones)

Built-in web server

// Start server on port 8000
php -S localhost:8000 -t /path/to/folder
// Start server on port 8000 using router.
// Check $_SERVER["REQUEST_URI"] in router.php for process routing
php -S localhost:8000 router.php

Limitations:

  • no .htaccess (no mod-rewrite)
  • developing environment only
DON'T use this server in anything resembling a production environment. It's intended only for use while developing. (We're in the business of making Web frameworks, not Web servers.)

$this support in closures

class Adder {

    private $value = 5;

    public function calculate(array $values) {
        return array_map(function($value) {
            return $value + $this->value;
        }, $values);
    }

}

$values = [0, 5, 10];
$calculatedValues = (new Adder)->calculate($values); // [5, 10, 15]

Session Upload Progress

# php.ini
session.upload_progress.enabled = 1;
session.upload_progress.prefix = upload_progress_;
session.upload_progress.name = PHP_SESSION_UPLOAD_PROGRESS;
<form action="upload.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
    <input type="file" name="file1" />
    <input type="file" name="file2" />
    <input type="submit" />
</form>
// you must send post with valid id
// only in this case $_SESSION will be populated with upload data
<form action="check.php" method="POST">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
    <input type="submit" />
</form>
$_SESSION["upload_progress_123"] = array(
    "start_time" => 1234567890,
    "content_length" => 57343257,
    "bytes_processed" => 453489,
    "done" => false,
    "files" => array(
        0 => array(
            "field_name" => "file1",
            "name" => "foo.avi",
            "tmp_name" => "/tmp/phpxxxxxx",
            "error" => 0,
            "done" => true,
            "start_time" => 1234567890,
            "bytes_processed" => 57343250,
        ),
        1 => array(
            "field_name" => "file2",
            "name" => "bar.avi",
            "tmp_name" => NULL,
            "error" => 0,
            "done" => false,
            "start_time" => 1234567899,
            "bytes_processed" => 54554,
        )
    )
);					

Traits

trait funnyTrait {
    private $name = 'meet.php';

    public function saySomething() {
        echo 'say ' . $this->name;
    }
};

trait weirdTrait {
    public function isThisEasternTime() {
        return true;
    }
}

class Test {
    use funnyTrait;
    use weirdTrait;
};

$test = new Test;
$test->saySomething(); // say meet.php
echo (int) $test->isThisEasternTime(); // 1

Example:

class Model {

    private static $_instance;

    public static function instance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self;
        }

        return self::$_instance;
    }

    public $value = 1;

};

$object1 = Model::instance();
$object2 = Model::instance();

$object1->value = 5;
echo $object2->value;

Since PHP 5.4 you can use traits to do this:

trait Singleton {
    private static $_instance;

    public static function instance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self;
        }

        return self::$_instance;
    }
}

class Model {
    use Singleton;
    public $value = 1;
};

$object1 = Model::instance();
$object2 = Model::instance();

$object1->value = 5;
echo $object2->value;

Backward Incompatible Changes

Thank you!

kariera.allegro.pl