5.3
名前空間のサポート
名前空間名の定義
- 非修飾名
名前空間区切り文字を含まない識別子。例)Foo
- 修飾名
名前空間区切り文字を含む識別子。例)Foo\Bar
- 完全修飾名
名前空間区切り文字を含む識別子のうち先頭が名前空間区切り文字で始まるもの。例)\Foo\Bar
とかnamespace \Foo
名前空間の定義
namespace + 完全修飾名
ただし完全修飾名しか指定できないので最初のバックスラッシュ\
は使用しないことが推奨される。
名前空間のインポート
use + 完全修飾名
ただし完全修飾名しか指定できないので(略
// エイリアス
use My\Full\Classname as Another;
// これは use My\Full\NSname as NSname と同じです
use My\Full\NSname;
// 関数をインポートします (PHP 5.6+)
use function My\Full\functionName;
// 定数をインポートします (PHP 5.6+)
use const My\Full\CONSTANT;
// グループ化(PHP 7.0+)
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
遅延静的束縛
遅延静的束縛は直近の "非転送コール" のクラス名を保存します。
転送コール | A::f()や$a->f()といったクラスやオブジェクトを明示的に指定した呼び出し |
---|---|
非転送コール | 静的呼び出しの場合はself::やparent::やstatic::呼び出し。または クラス階層の中での forward_static_call() での呼び出し。 |
ジャンプラベル
gotoなやつ。きっと使うことない
クロージャ
PHP5.3からネイティブクロージャが使える。バインドする変数はuseが必要。
PHP5.4以降では、$thisは暗黙的にバインドされる。また静的な無名関数も使えるようになった。
マジックメソッドの追加
__callStatic()
と__invoke()
の追加
public mixed __call ( string $name , array $arguments )
__call() は、 アクセス不能メソッドをオブジェクトのコンテキストで実行したときに起動します。
public static mixed __callStatic ( string $name , array $arguments )
__callStatic() は、 アクセス不能メソッドを静的コンテキストで実行したときに起動します。
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// 注意: $name は大文字小文字を区別します
echo "Calling object method '$name' " . implode(', ', $arguments). "\n";
}
/** PHP 5.3.0 以降 */
public static function __callStatic($name, $arguments)
{
// 注意: $name は大文字小文字を区別します
echo "Calling static method '$name' " . implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context'); // PHP 5.3.0 以降
?>
Calling object method 'runTest' in object context
Calling static method 'runTest' in static context
mixed __invoke ([ $... ] )
__invoke() メソッドは、 スクリプトがオブジェクトを関数としてコールしようとした際にコールされます。
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
int(5)
bool(true)
Nowdoc
ヒアドキュメント:ダブルクオーテーションで囲った扱い。パースする。
Nowdoc:シングルクォーテーションで囲った扱い。パースしない。
// ヒアドキュメント
$str <<<EOF
hoge
EOF
// or
$str <<<"EOF"
hoge
EOF
// Nowdoc
$str <<<'EOF'
hoge
EOF
ヒアドキュメントの追加機能
- 静的なクラスプロパティ、定数の初期化に使えるように
- ヒアドキュメントはダブルクオーテーションを使って宣言できるように("EOF")
定数の追加機能
クラス外でconstを使って定義可能になった
エルビス演算子
三項演算子の短縮記法。?:
横から見るとエルビス・プレスリー?
$a ?: $b
は
$a ? $a : $b
に展開される
静的クラスメンバへの動的アクセス
<?php
class C {
public static $foo = 123;
}
$a = "C";
echo $a::$foo;
?>
123
例外のネスト
<?php
class MyCustomException extends Exception {}
try {
throw new MyCustomException("Exceptional", 112);
} catch (Exception $e) {
/* 三番目のパラメータとして、$e を
* RuntimeException に渡しています */
throw new RuntimeException("Rethrowing", 911, $e);
}
?>
その他
- HTTPストリームラッパー は、200 から 399 までのステータスコードを成功したものとみなすようになりました。
- 循環参照用のガベージコレクタが追加され、デフォルトで有効になりました。
- mail()関数が送信メールのログを記録できるようになりました (注意: この関数を使って送信されたメールのみが対象です)
5.4
トレイト
名前の衝突を解消する方法がいろいろあるが省略。
trait ezcReflectionReturnInfo {
function getReturnType() { /*1*/ }
function getReturnDescription() { /*2*/ }
}
class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
配列の短縮構文
$a = [1, 2, 3, 4];
関数の戻り値を配列として
foo()[0]
クロージャの$this
クロージャにthisが暗黙的に束縛されるように。staticにすると暗黙的な束縛はされない。
class A
{
private $value = 'A';
public function getf()
{
return function()
{
echo($this->value);
};
}
public function getsf()
{
return static function()
{
echo($this->value);
};
}
}
(new A)->getf()(); // A
(new A)->getsf()(); // Using $this when not in object context in
callで渡したthisも束縛される。
// php7.0+
(function ()
{
echo($this->value);
})->call(new class
{
public $value = 'hoge';
});
インスタンス生成時のメンバアクセス
(new C)->v;
(new C)->f();
Class::{expr}()構文
式で動的にメンバアクセスする。
class Hoge
{
public static function huga()
{
echo ('Hoge::huga');
}
}
Hoge::{(function(){return 'huga';})()}();
その他
- = が常に有効になりました。short_open_tagの設定にかかわらずいつでも使えます。
- 二進数フォーマットが追加されました。0b001001101 のように使えます。
- パースエラー時のパーサからのメッセージや関数コール時の引数が間違っている場合の警告メッセージが改善されました。
- セッションモジュールで、ファイルのアップロード状況を追跡できるようになりました。
- CLI モードで動く、開発用のウェブサーバー が組み込まれました。
5.5
ジェネレーター
yield
キーワードで実装する。
ジェネレーターをyieldについて
finallyキーワード
try-catchブロックでfinallyが使える。finallyブロックは例外のあるなしに関わらず必ず実行される。
try {
throw new Exception();
} catch (Exception $e) {
echo '捕捉した例外: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}
foreachのlist()対応
$array = [
[1, 2],
[3, 4],
];
foreach ($array as list($a, $b)) {
echo "A: $a; B: $b\n";
}
empty()のexpr対応
引数が変数じゃなくてもよくなった。
function always_false() {
return false;
}
if (empty(always_false())) {
echo "This will be printed.\n";
}
arrayリテラル、stringリテラルのデリファレンス
リファレンスはメモリ上のどこかの実態を指してるアドレスのようなものでポインタとほとんど同じ概念。デリファレンスはそのリファレンスの指してる中身のデータを取得すること。
// array
echo [1, 2, 3][0];
// string
echo 'PHP'[0];
::class
クラス名の完全修飾名を取得できるように。
namespace Name\Space;
class ClassName {}
echo ClassName::class; //Name\Space\ClassName
foreachのkeyの非スカラー化
これでiterator::key()がスカラー以外を返せるようになった。
class HogeIterator implements \Iterator
{
protected $index = 0;
protected $limit = 3;
public function current()
{
return $this->index * $this->index;
}
public function key()
{
return ['key' => $this->index];
}
public function next()
{
++$this->index;
}
public function rewind()
{
$this->index = 0;
}
public function valid()
{
return $this->index < $this->limit;
}
}
foreach(new HogeIterator() as $key => $value) {
echo($key['key'] . "^2 = " . $value . PHP_EOL);
}
その他
- 新しいパスワードハッシュAPIが用意され、より簡単にパスワードをハッシュしたり管理したりできるようになりました。詳細はpassword_hash()のドキュメントを参照ください。
- ZendOptimiser+のオペコードキャッシュ機能が、OPcache拡張モジュールとしてPHPに追加されました。
- Apache2.4ハンドラSAPIがWindowsに対応するようになりました。
- GD拡張モジュールに、さまざまな改良が加えられました。
5.6
定数式
定数やプロパティの宣言、関数のデフォルト引数などでconstの初期化にスカラー式を使えるように。
<?php
const A = 1;
class Hoge
{
public const A = A + 10;
public static function f($value = self::A+100)
{
echo($value.PHP_EOL);
}
}
echo(A.PHP_EOL); // 1
echo(Hoge::A.PHP_EOL); // 10
Hoge::f(); // 100
...による可変個引数の関数
...
演算子が追加されてfunc_get_args()が不要に。
function f($req, $opt = null, ...$params) {
// $params は配列で、残りのすべての引数が含まれます
printf('$req: %d; $opt: %d; パラメータ数: %d'."\n",
$req, $opt, count($params));
}
f(1); // $req: 1; $opt: 0; パラメータ数: 0
f(1, 2); // $req: 1; $opt: 2; パラメータ数: 0
f(1, 2, 3); // $req: 1; $opt: 2; パラメータ数: 1
f(1, 2, 3, 4); // $req: 1; $opt: 2; パラメータ数: 2
f(1, 2, 3, 4, 5); // $req: 1; $opt: 2; パラメータ数: 3
...によるアンパック
関数の呼び出し時に ... 演算子が使えるように。配列やTraversableオブジェクトを引数リストにアンパックして渡してくれます。
function add($a, $b, $c) {
return $a + $b + $c;
}
$operators = [2, 3];
echo add(1, ...$operators);
累乗演算子 **
$a = 2;
$a **= 3; // 8
use functionとuse const
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();
}
phpdbg
SAPIモジュールにphpdbg
というデバッガーを含むように。xdebugとさよならできるかも?
phpdbgのヘルプを和訳してみた
https://qiita.com/hnw/items/63e85a1a26a8ccfb7d31
その他
- エンコーディングに依存する関数
htmlentities()
やhtml_entity_decode()
そしてhtmlspecialchars()
におけるデフォルトの文字セットとしてdefault_charsetを利用するようになりました。この設定のデフォルト値はUTF-8です。 -
php://input
が再オープンできるようになり、必要に応じて何度でも読めるようになりました。 - 2ギガバイトより大きいサイズのファイルもアップロードできるようになりました。
- GMPオブジェクトが、演算子のオーバーロードやスカラー型へのキャストに対応するようになりました。
-
hash_equals()
関数が追加されました。この関数は、二つの文字列の比較を一定の時間で行います。 - マジックメソッド
__debugInfo()
が追加されました。 - ハッシュアルゴリズム
gost-crypto
が追加されました。 - SSL/TLSのサポートに幅広い改良が加わりました。
- pgsql拡張モジュールが、非同期の接続や問い合わせに対応しました。
7.0
スカラー型宣言
タイプヒンティング。関数を呼ぶ際の引数の型を指定できる。不正な型であった場合はPHP5ではrecoverable fatal error
、PHP7ではTypeError
例外をスローする。。
デフォルトでは違う型が渡されても可能な限り期待されている型に暗黙的に変換される。declare(strict_types=1)
の場合、厳密な型チェックが行われ指定された型以外ではエラーとなる。
もともとPHP5.0からあったタイプヒンティングにスカラーが追加された。スカラータイプヒンティング(STH)
型 | 対応バージョン |
---|---|
クラス/インターフェイス | php5.0 |
self | php5.0 |
array | php5.1 |
callable | php5.4 |
bool | php7.0 |
float | php7.0 |
int | php7.0 |
string | php7.0 |
iterable | php7.1 |
スカラー型のエイリアスクラス(たとえばboolではなくboolean)を用いるとスカラーではなく、ちゃんとクラスとして解釈されboolは渡せなくなる。
// php7.0+
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
echo 'Error: '.$e->getMessage();
}
// int(3)
// Error: Argument 1 passed to sum() must be of the type integer, float given, called in - on line 10
戻り値の型宣言
戻り値にもタイプヒンティングが指定できるように。もちろんstrict_typesが影響する。
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
null合体演算子 ??
すごいなまえ…。null coalescing operatorが英名。単なるシンタックスシュガー。
$username = $_GET['user'] ?? 'nobody';
// 上のコードは、次のコードと同じ意味です。
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
宇宙船演算子
すごいなまえ…笑かそうとしてるの?spaceship operator。ソート関数を作るときに便利かな。
A <=> B
A > B
なら1
A = B
なら0
A < B
なら-1
無名クラス
interface Animal
{
public function say();
}
trait WanAnimal
{
public function say()
{
echo('WanWan!!')
}
}
trait GaooAnimal
{
public function say()
{
echo('gaooo!!')
}
}
function say(Animal $ani) {
$ani->say();
}
say(new class implements Animal {
use GaooAnimal;
});
ちゃんとOOPしてる感が。ちゃんとクラス定義してインターフェイスを実装してるから正確にはちがうんだけど、ダックタイピングみたい。
Closure::call()
public mixed Closure::call ( object $newthis [, mixed $... ] )
クロージャを一時的にnewthisに束縛し、指定したパラメータでそれを呼び出します。
Expectation
assert()関数が言語構造になり、expectation の定義を満たすように。 たとえば開発環境やテスト環境では有効だけど運用環境では除去されてコストがかからないアサーションが可能に。
// php5およびphp7
bool assert ( mixed $assertion [, string $description ] )
// php7
bool assert ( mixed $assertion [, Throwable $exception ] )
asset()用ディレクティブ
-
zend.assertions
1:コードを生成して実行する(開発モード)
0:コードを生成するが、実行時には読み飛ばす
-1:コードを生成しない(運用モード) -
assert.exception
1:アサーションに失敗した場合には、exceptionで指定したオブジェクトをスローするか、exceptionを指定していない場合はAssertionErrorオブジェクトをスローします。
0:先述のThrowableを使ったり生成したりしますが、そのオブジェクト上で警告を生成するだけであり、スローしません(PHP5と互換性のある挙動です)。
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(false, new CustomError('Some error message'));
useのグループ化
// php5.6-
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// PHP7.0+
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
ジェネレータのreturn
PHP 5.5 で導入されたジェネレータの機能拡張。returnでジェネレータが最終的に返す式を指定する。
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
ジェネレータの委譲
ジェネレータでyield from
を使うと別のジェネレータやTraversableオブジェクトや配列に委譲できるように。
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
// 1 2 3 4
intdiv()による整数の除算
オペランドに対して整数の除算を行いその結果を返す。
var_dump(intdiv(10, 3)); // int(3)
その他
- define()で配列の定数を定義できるようになりました。
- Unicodeコードポイントエスケープ構文。Unicodeのコードポイントを十六進形式で受け取って、それをUTF-8で(ダブルクォートで囲まれた文字列あるいはヒアドキュメントとして)出力します。
- unserialize()にoptionパラメーターが追加されました。allowed_classesで受け付けるクラスを指定するとそれ以外のクラスは__PHP_Incomplete_Classクラスのインスタンスに変換する。
- ICUのさらなる機能を利用するために、新しくIntlCharクラスが追加されました。このクラスには数々のstaticメソッドと定数が定義されており、これらを使ってUnicodeの文字を操作できます。
- session_start()にオプションの配列を渡せるようになりました。
- 新しいpreg_replace_callback_array()関数が追加された
- CSPRNG関数。暗号論的に安全な整数値および文字列を生成する、プラットフォームに依存しない二つの新しい関数が追加されました。random_bytes()とrandom_int()です。
- list()が常にArrayAccessを実装したオブジェクトをアンパックできるように。
- クローンしたクラスのメンバーにアクセスできるようになりました。(clone$foo)->bar()のようにできるということです。
7.1
nullable
パラメータや返り値の型宣言でnullable指定ができるように。型の前にクエスチョンマークをつける。nullableをつけると指定の型以外にnullも渡せるように。
function test(?string $name)
{
var_dump($name);
}
test('elePHPant');
test(null);
test();
// string(10) "elePHPant"
// NULL
// Uncaught Error: Too few arguments to function test(), 0 passed in...
void関数
返り値の型としてvoidが追加。voidにした関数はreturnを省略するか、空のreturnを使う必要がある。またvoid関数からnullは返せない。void関数を評価した場合はnullとなり警告は発生しない。
function swap(&$left, &$right): void
{
if ($left === $right) {
return;
}
$tmp = $left;
$left = $right;
$right = $tmp;
}
$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);
// null
// int(2)
// int(1)
Symmetric array destructuring
配列の短縮構文[]やlist()を使って代入時に配列の中身を取り出せるように。foreachでも使える。
$data = [
[1, 'Tom'],
[2, 'Fred'],
];
// list() 形式
list($id1, $name1) = $data[0];
// [] 形式
[$id1, $name1] = $data[0];
// list() 形式
foreach ($data as list($id, $name)) {
// $id と $name を使う処理をここに書きます
}
// [] 形式
foreach ($data as [$id, $name]) {
// $id と $name を使う処理をここに書きます
}
クラス定数のアクセス範囲指定
class ConstDemo
{
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}
iterable擬似型
関数のパラメーターや戻り値の型で指定できる疑似型iterableの追加されました。
iterableは配列とTraversableインターフェイスを実装したオブジェクトを受け取ることができる疑似型です。実際にそのオブジェクトを作れたりはしません。Closureを受け取ることのできるcallableと同じようなものですね。
ちなみにTraversableインターフェイスというのはforeachで受け取ることができるオブジェクトのことで、配列はTraversableではありません。これは抽象的なインターフェイスなので実際にPHPで実装するにはこれを継承したIteratorクラスとかIteratorAggregateクラスを継承して実装します。
function iterator(iterable $iter)
{
foreach ($iter as $val) {
//
}
}
例外処理における複数の例外のcatch
パイプ文字|
を使います。
try {
// 何かのコード
} catch (FirstException | SecondException $e) {
// FirstException と SecondException をこのブロックで処理します
}
配列の短縮構文[]やlist() におけるキーのサポート
配列のkeyが整数でなかったりシーケンシャルでなかったりした場合でもvalueを取得できるようになります。Symmetric array destructuringと同じですね。
$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
// list() 形式
list("id" => $id1, "name" => $name1) = $data[0];
// [] 形式
["id" => $id1, "name" => $name1] = $data[0];
// list() 形式
foreach ($data as list("id" => $id, "name" => $name)) {
// $id と $name を使う処理をここに書きます
}
// [] 形式
foreach ($data as ["id" => $id, "name" => $name]) {
// $id と $name を使う処理をここに書きます
}
負の文字列オフセットのサポート
文字列操作関数のうちオフセット指定のできるものすべてについて、負のオフセットを指定できるようになりました。[]や{}による文字列への文字単位のアクセスについても同様です。負のオフセットは、文字列の末尾からのオフセットと解釈されます。
var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));
// string (1) "e"
// int(3)
$string = 'bar';
echo "The last character of '$string' is '$string[-1]'.\n";
// The last character of 'bar' is 'r'.
Closure::fromCallable()
Closureクラスに新しい静的メソッドが追加されました。現在のスコープを用いて指定されたcallableから新しい無名のClosureを作って返します。
public static Closure Closure::fromCallable ( callable $callable )
class Test
{
public function exposeFunction()
{
return Closure::fromCallable([$this, 'privateFunction']);
}
private function privateFunction($param)
{
var_dump($param);
}
}
$privFunc = (new Test)->exposeFunction();
$privFunc('some value');
// string(10) "some value"
その他
- ext/opensslにおけるAEADのサポート。openssl_encrypt()およびopenssl_decrypt()の追加のパラメータで、AEAD(GCMモードおよびCCMモード)をサポートするようになりました。
- 非同期シグナルハンドリング。関数pcntl_async_signals()が追加されました。これは、tickを使わない非同期シグナルハンドリングを有効にするものです。
- ext/curlにおけるHTTP/2サーバープッシュのサポート。CURL拡張モジュールがサーバープッシュに対応するようになりました(curlバージョン7.46以降が必要です)。curl_multi_setopt()関数に新しい定数CURLMOPT_PUSHFUNCTIONを指定すれば、この機能を使えます。また、定数CURL_PUSH_OKとCURL_PUSH_DENYも新たに追加されました。これらは、サーバープッシュコールバックの実行を許可したり拒否したりするものです。 7.2
7.2
object型
任意のオブジェクトに対して関数の引数や戻り値のタイプヒンティングの型として使えます。
function test(object $obj) : object
{
return new SplQueue();
}
test(new StdClass());
名前指定による拡張モジュールのロード
読み込む共有モジュールの指定に拡張子を記載する必要がなくなった。php.iniファイルでの指定だけでなくdl()関数による指定でも同様です。
抽象メソッドのオーバーライド
ある抽象クラスが別の抽象クラスを継承しているときに、継承元クラスの抽象メソッドをオーバーライドできるように。
abstract class A
{
abstract function test(string $s);
}
abstract class B extends A
{
// オーバーライドしましたが、パラメータの反変性や戻り値の共変性は維持しています。
abstract function test($s) : int;
}
パラメータの型の拡大変換
メソッドをオーバーライドやインターフェイスを実装で元のパラメータの型指定を省略できるように。
interface A
{
public function Test(array $input);
}
class B implements A
{
public function Test($input){} // $input の型指定を省略
}
名前空間のグループ指定における最後のカンマの許可
use Foo\Bar\{
Foo,
Bar,
Baz,
};
その他
- モダンな暗号ライブラリである Sodium が PHP コアモジュールに含まれるようになりました。
- パスワードハッシュ API に Argon2 が追加されました。
- PDO の文字列型が拡張され、 プリペアをエミュレートする際に NCHAR 型をサポートするようになりました。
- PDO のデバッグ情報で、PDOStatement::debugDumpParams() メソッドが改良されて、 データベースに送信される SQL を表示できるようになりました。 これは、プレースホルダの内容をバインド変数の値で置き換えた後の生のクエリです。 この機能は、プリペア機能のエミュレートをデバッグしやすくするために用意されました (そのため、プリペア機能のエミュレートが有効になっているときしか使えません)。
- LDAP 拡張モジュールが EXOP をサポートするようになりました。
- ソケット拡張モジュールが、アドレス情報のルックアップや 接続、バインド、explainに対応するようになりました。
- proc_nice() 関数が Windows でも使えるようになりました。
- pack() と unpack() が、 リトルエンディアンとビッグエンディアンの両方の float や double に対応するようになりました。
- pack() と unpack() が、 リトルエンディアンとビッグエンディアンの両方の float や double に対応するようになりました。 cc