takafumi blog

日々の勉強メモ

PHP5.3~5.6の新機能を確認

環境   PHP 5.3 PHP 5.4 PHP 5.5 PHP 5.6
PHP5.3~5.6の新機能をざっと確認。

【PHP5.3~】名前空間
【PHP5.3~】遅延静的束縛
【PHP5.3~】goto文
【PHP5.3~】【PHP5.4~】クロージャ(無名関数)
【PHP5.3~】class外でのconst定義
【PHP5.6~】定数式
【PHP5.3~】三項演算子の短縮形(エルビス演算子)
【PHP5.3~】静的メソッドへの動的アクセス
【PHP5.4~】トレイト
【PHP5.4~】配列の短縮構文
【PHP5.4~】foo()[0]のように、関数の返り値を配列として扱える
【PHP5.4~】インスタンス生成時にメンバーへのアクセスが可能に
【PHP5.4~】Class::{expr}() 構文のサポート
【PHP5.5~】ジェネレータ
【PHP5.5~】finallyキーワード追加
【PHP5.5~】foreachがlist()対応
【PHP5.5~】emptyが式に対応
【PHP5.5~】Array、stringのデリファレンス
【PHP5.5~】::class によるクラス名解決
【PHP5.5~】foreach が非スカラーのキーに対応
【PHP5.6~】可変引数
【PHP5.6~】累乗演算子
【PHP5.6~】use function および use const

OPcacheやphpdbgは長くなるので、いずれ別記。

また全機能を見たい場合は、公式マニュアルを。
PHP: 付録 - Manual





【PHP5.3~】名前空間

PHP: 名前空間 - Manual

<?php // MyProject.php

// 名前空間の定義
namespace My\Project;

class Hoge{
    public function fuga()
    {
        echo 'hoge,fuga';
    }
}
echo __NAMESPACE__ . "\n";
<?php // UseProj.php
require_once 'MyProject.php';

// 名前空間の別名を定義
use My\Project as Proj;

// 名前空間付きでクラスを呼び出し
$obj = new Proj\Hoge();
echo get_class($obj) . "\n";

try {
    // グローバル名前空間から呼び出し
    throw new \Exception('Throw Exception.');
} catch (Exception $e) {
    echo $e->getMessage() . "\n";
}

実行結果は以下ような出力となる。

$ php UseProj.php
My\Project
My\Project\Hoge
Throw Exception.



【PHP5.3~】遅延静的束縛

PHP: 遅延静的束縛 (Late Static Bindings) - Manual

<?php // Static.php
class A
{
    public static function hoge()
    {
        echo __CLASS__ . "\n";
    }
    public static function fuga()
    {
        self::hoge();
        static::hoge();
    }
}

class B extends A
{
    public static function hoge()
    {
        echo __CLASS__ . "\n";
    }
}

B::fuga();

実行結果は以下ような出力となる。

A
B

selfは記述された側の関数を呼び出すが、staticは呼び出し側の関数を呼び出す。



【PHP5.3~】goto文

PHP: goto - Manual

manualにはイロイロと例が書いてあるが、正直無理に使う必要は無いかなと思う。
しいて言うならネストされたループ分から抜けるときは、break文よりわかりやすいかもしれない。

<?php
for ($i=0; $i<20; $i++) {
    if($i === 10){
        goto end;
    }
    echo $i . ',';
}
echo "\nFinish!\n";

end:
echo "\nGoTo end\n";

実行結果は以下ような出力となる。

0-0,0-1,0-2,0-3,0-4,1-0,1-1,1-2,1-3,1-4,2-0,2-1,2-2,
GoTo end

ただ以下の参考先にもあるように、if~elseやtry~catchの飛び込むことができたりする危険な使い方もできるので注意が必要。
PHPとgoto文 (PHP Advent Calendar 2011 24日目) - 泥のように




【PHP5.3~】【PHP5.4~】クロージャ(無名関数)

PHP: 無名関数 - Manual

5.3~からクロージャを使えるようになった。
5.4~からはクロージャ内で$thisキーワードが使えるようになった。

<?php
<?php
class MyClass
{
    private $fuga = 'Fuga';

    function hoge()
    {
        // 5.3では$thisをクロージャ内に持ち込めなかった
        $self = &$this;
        $f53 = function($a, $b) use ($self){
            echo $a . '-' . $b . ':' . $self->fuga . "\n";
        };
        // 5.4では問題なし
        $f54 = function($a, $b){
            echo $a . '.' . $b . ':' . $this->fuga . "\n";
        };

        $f53('5' , '3');
        $f54('5' , '4');
    }
}

$obj = new MyClass();
$obj->hoge();

実行結果は以下ような出力となる。

5-3:Fuga
5.4:Fuga



【PHP5.3~】class外でのconst定義

PHP: 構文 - Manual

5.3未満ではconstキーワードはclass内でしか使えないが、5.3からはクラスの外、名前空間内もしくはグローバル空間でもconstで定数を定義する事ができる。

5.6未満ではconstにはスカラ式が定義できず、defineは定義できた。
が、5.6以上の場合はconstでもスカラ式を定義できるようになり、名前空間を定義できる事を考えると、defineを使う理由は少なくなった気がする。

<?php // MyProject.php
namespace My\Project;
const CONSTANT = 'NAMESPACE CONSTANT';

class MyClass
{
    const CONSTANT = 'CLASS CONSTANT';
}
<?php // Const.php
require_once('MyProject.php');
const CONSTANT = 'GLOBAL CONSTANT';

echo \CONSTANT . "\n";
echo \My\Project\CONSTANT . "\n";
echo \My\Project\MyClass::CONSTANT . "\n";

実行結果は以下ような出力となる。

$ php Const.php
GLOBAL CONSTANT
NAMESPACE CONSTANT
CLASS CONSTANT



【PHP5.6~】定数式

以下のようにconstに式を定義できるようになった。

const ONE = 1;
const TWO = ONE * 2;

class C {
    const THREE = TWO + 1;
    const ONE_THIRD = ONE / self::THREE;
    const SENTENCE = 'THREE の値は '.self::THREE;
}



【PHP5.3~】三項演算子の短縮形(エルビス演算子)

PHP: 比較演算子 - Manual

以下のように書けるようになった。

<?php
$a = 'hoge';

// PHP5.3未満
echo $a ? $a : 'Null';
echo "\n";

// PHP5.3以上
echo $a ?: 'Null';
echo "\n";

「?:」を90度回転するとエルビス・プレスリーの顔のように見えることから、エルビス演算子とも呼ばれる。



【PHP5.3~】静的メソッドへの動的アクセス

つまり以下のような書き方ができるようになった。

<?php
class A{
    static public function hoge()
    {
        echo __CLASS__ . "\n";
    }
}
class B{
    static public function hoge()
    {
        echo __CLASS__ . "\n";
    }
}

$class = 'A';
$class::hoge();

$class = 'B';
$class::hoge();

実行結果は以下ような出力となる。

A
B



【PHP5.4~】トレイト

http://php.net/manual/ja/language.oop5.traits.php

簡単にいうとメソッドだけを再利用するための仕組みです。

<?php
class Base {
    public function say() {
        echo "Hello\n";
    }
}

trait World {
    public function say() {
        parent::say();
        echo "World!\n";
    }
}

class HelloWorld extends Base {
    use World;
}

$o = new HelloWorld();
$o->say();

実行結果は以下ような出力となる。

Hello
World!




【PHP5.4~】配列の短縮構文

以下のような配列定義が可能になった

<?php
// ~5.3
$a53 = array(1, 2, 3, 4, 5);
$b53 = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);

// 5.4~
$a54 = [1, 2, 3, 4, 5];
$b54 = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5];

var_dump($a53 === $a54);
var_dump($b53 === $b54);

実行結果は以下ような出力となる。

bool(true)
bool(true)



【PHP5.4~】foo()[0]のように、関数の返り値を扱えるようになった

返り値が配列となるときに、以下のように書くことができる。

<?php
function hoge()
{
    return array(1, 2, 3);
}

echo hoge()[1] . "\n";



【PHP5.4~】インスタンス生成時にメンバーへのアクセスが可能に

以下のように、インスタンス作成時にメンバにアクセスができるようになった。

<?php
class My
{
    public $hoge = 'Hoge';
    public function __construct()
    {
        return $this;
    }
    public function fuga()
    {
        echo "Fuga\n";
    }
}

echo (new My)->hoge . "\n";
echo (new My)->fuga();



【PHP5.4~】Class::{expr}() 構文のサポート

以下のような事が可能になった。

<?php
class MyClass
{
    public static function fuga()
    {
        echo "HogeFuga!\n";
    }
    public function hoge()
    {
        return 'fuga';
    }
    public static function hoge2()
    {
        return 'fuga';
    }
}

$obj = new MyClass();
MyClass::{$obj->hoge()}();

MyClass::{MyClass::hoge2()}();

実行結果は以下ような出力となる。

HogeFuga!
HogeFuga!



【PHP5.5~】ジェネレータ

yeildキーワードを利用し、シンプルなイテレータIteratorインターフェースを実装せずに使える。

<?php
function xrange($start, $limit, $step = 1) {
    for ($i = $start; $i <= $limit; $i += $step) {
        yield $i;
    }
}

foreach (xrange(1, 9, 2) as $number) {
    echo "$number ";
}
echo "\n";

実行結果は以下ような出力となる。

1 3 5 7 9



【PHP5.5~】finallyキーワード追加

try-catchにfinallyを使えるようになった。

<?php
for ($i=0; $i<2; $i++ ) {
    try {
        if ($i === 0) echo $i . "\n";
        if ($i === 1) throw new Exception("Exception:" . $i . "\n");_

    } catch (Exception $e) {
        echo $e->getMessage();
    }
}

実行結果は以下ような出力となる。

0
Exception:1



【PHP5.5~】foreachがlist()対応

<?php
$array = [
    [1, 2, 3],
    [4, 5, 6],
];

foreach ($array as list($a, $b, $c)) {
    echo "A: $a; B: $b; C: $c\n";
}

実行結果は以下ような出力となる。

A: 1; B: 2; C: 3
A: 4; B: 5; C: 6



【PHP5.5~】emptyが式に対応

5.5未満ではempty()は変数以外は引数に取れなかったが、5.5からは以下のように式を引数にとれる。

<?php
function always_false()
{
    return false;
}

if (empty(always_false())) {
    echo "This will be printed.\n";
}



【PHP5.5~】Array、stringのデリファレンス

Array,stringをデリファレンスし、個々の要素や文字に直接アクセスできる。

<?php
// ~5.4まではこうしかできなかった
$arr = array(1, 2, 3, 4, 5);
$str = "abcdefgh";

echo $arr[1] . "\n";
echo $str[1] . "\n";

// 5.5~ は直接扱える
echo [6, 7, 8, 9, 10][1] . "\n";
echo 'ijklmnopqrstu'[1] . "\n";

実行結果は以下ような出力となる。

2
b
7
j



【PHP5.5~】::class によるクラス名解決

ClassName::classでClassNameの完全修飾名を取得できる。

namespace Name\Space;
class ClassName {}

echo ClassName::class . "\n";

実行結果は以下ような出力となる。

Name\Space\ClassName



【PHP5.5~】foreach が非スカラーのキーに対応

以下のようにforeachのキーを参照できる。
5.4まではint,stringに限られていた。

<?php
$people = new ArrayIterator(array('John', 'Jane', 'Jack', 'Judy'));
$roles  = new ArrayIterator(array('Developer', 'Scrum Master', 'Project Owner'));

$team = new MultipleIterator($flags);
$team->attachIterator($people, 'person');
$team->attachIterator($roles, 'role');

// ~PHP5.4
echo "~PHP5.4 ----------------\n";
foreach ($team as $member) {
    print_r($team->key());
}
// PHP5.5~
echo "~PHP5.4 ----------------\n";
foreach ($team as $k => $v){
    print_r($k);
}

実行結果は以下ような出力となる。

~PHP5.4 ----------------
Array
(
    [person] => 0
    [role] => 0
)
Array
(
    [person] => 1
    [role] => 1
)
Array
(
    [person] => 2
    [role] => 2
)
Array
(
    [person] => 3
    [role] =>
)
PHP5.5~ ----------------
Array
(
    [person] => 0
    [role] => 0
)
Array
(
    [person] => 1
    [role] => 1
)
Array
(
    [person] => 2
    [role] => 2
)
Array
(
    [person] => 3
    [role] =>
)



【PHP5.6~】可変引数

func_get_args call_user_funcを使わず、可変引数を扱えるようになった。

<?php
function hoge(...$params)
{
    fuga(...$params);
}
function fuga(...$params)
{
    print_r($params);
}

hoge(1, 2, 3);

実行結果は以下ような出力となる。

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)




【PHP5.6~】累乗演算子

今まで無かったのか・・・

<?php
echo 2 ** 2 ** 2;

実行結果は以下ような出力となる。

16



【PHP5.6~】use function および use const

クラスだけではなく関数や定数もインポートできるように。

<?php
namespace Name\Space {
    const FOO = 42;
    function f() { echo __FUNCTION__."\n"; }
}

namespace {
    use const Name\Space\FOO;
    use function Name\Space\f;

    echo FOO."\n";
    f();
}

実行結果は以下ような出力となる。

42
Name\Space\f