新機能
PHP コア
型付きプロパティ
クラスのプロパティは、新たに型宣言をサポートするようになりました
<?php
class User {
public int $id;
public string $name;
}
?>
$user->id
には int の 値だけを、そして $user->name
には string の値だけを代入できるように強制します。
アロー関数
アロー関数は、暗黙的な値スコープを持った関数を定義する簡便な文法を提供します。
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>
戻り値の型を狭めたり、引数の型を広げたりする
次のようなコードが動作するようになります:
<?php
class A {}
class B extends A {}
class Producer {
public function method(): A {}
}
class ChildProducer extends Producer {
public function method(): B {}
}
?>
Null 合体代入演算子
<?php
$array['key'] ??= computeDefault();
// は、以下にほぼ等しい
if (!isset($array['key'])) {
$array['key'] = computeDefault();
}
?>
配列内での値のアンパック
<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>
数値リテラルのセパレータ
数値リテラルは、桁と桁の間にアンダースコアを挿入できるようになりました。
<?php
6.674_083e-11; // float
299_792_458; // decimal
0xCAFE_F00D; // hexadecimal
0b0101_1111; // binary
?>
弱い参照
弱い参照 により、オブジェクトが破棄されるのを妨げないオブジェクトへの参照を保持することが可能です。
__toString() から例外をスロー可能に
__toString() から例外をスローできるようになりました。以前は、この場合には致命的なエラーが発生していました。この関数内に既に存在する、回復可能な致命的なエラーは Error 例外クラスに変換されます。
CURL
CURLFile は、CURL拡張モジュールが libcurl 7.56.0 より新しいものでビルドされた場合は、通常のファイル名に加えて、ストリームラッパーをサポートするようになります。
Filter
FILTER_VALIDATE_FLOAT
フィルタは
min_range
と max_range
オプションをサポートするようになりました。
これは、FILTER_VALIDATE_INT
と同じセマンティクスです。
FFI
FFI は、ネイティブ関数を呼び出したり、ネイティブな値にアクセスしたり、Cライブラリで定義されたデータ構造を生成/アクセスする簡単な方法を提供する新しい拡張モジュールです。
GD
画像に scatter フィルタを適用するための
IMG_FILTER_SCATTER
が追加されました。
Hash
Castagnoli 多項式を使った crc32c
ハッシュが追加されました。
CRC32 バリアントは、 iSCSI, SCTP, Btrfs, ext4
のようなストレージシステムで使われています。
マルチバイト文字列
str_split() と同等の機能を提供するものの、バイトではなく、コードポイント単位で動作する mb_str_split() 関数が追加されました。
OPcache
コードを事前ロードする機能 がサポートされました。
正規表現 (Perl互換)
preg_replace_callback() および preg_replace_callback_array()
関数は、追加のフラグを受け入れるようになりました。
PREG_OFFSET_CAPTURE
と PREG_UNMATCHED_AS_NULL
です。これは、コールバック関数に渡される matches配列のフォーマットに影響します。
PDO
ユーザー名とパスワードが、PDO DSN の一部として指定できるようになりました。対象となるのは、mysql, mssql, sybase, dblib, firebird, oci ドライバです。以前は、この機能は pgsql ドライバでのみサポートされていました。ユーザー名/パスワードがコンストラクタとDSNの両方で指定された場合は、コンストラクタの指定が優先します。
SQLクエリのクエスチョンマークが、パラメータのプレースホルダーとして解釈されるのを防ぐためにエスケープできるようになりました。??
を書くことで、単一のクエスチョンマークをデータベースに送信できるようになります。PostgreSQL のJSONのキーが存在するかを確認する演算子 (?
) として使って下さい。
PDO_OCI
PDOStatement::getColumnMeta() が利用できるようになりました。
PDO_SQLite
PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT)
は、ステートメントが読み取り専用かどうか、つまりそれがデータベースを変更しないかをチェックできるようになりました。
PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES,
true)
関数によって、PDO::errorInfo() と
PDOStatement::errorInfo() 経由で SQLite3
の拡張結果コードを使えるようになりました。
SQLite3
最新の拡張結果コードを取得するために、 SQLite3::lastExtendedErrorCode() が追加されました。
SQLite3::enableExtendedResultCodes($enable = true)
が追加されました。これによって、
SQLite3::lastErrorCode()
が拡張結果コードを返すようになります。
標準ライブラリ
strip_tags() をタグ名の配列とともに使う
strip_tags()
関数は、許可するタグの配列も受け入れるようになりました。つまり、strip_tags($str,
'<a><p>')
の代わりに、 strip_tags($str,
['a', 'p'])
と書けるようになったということです。
カスタムオブジェクトのシリアル化
新しいカスタムオブジェクトのシリアル化の機構が追加されました。これは、新しいふたつのマジックメソッド
__serialize
と __unserialize
を使います。
<?php
// オブジェクトに必要な状態を全て保持した配列を返す
public function __serialize(): array;
// 与えられた data 配列から、オブジェクトの状態を復元する
public function __unserialize(array $data): void;
?>
引数を渡さずに array_merge 系の関数を使用する
array_merge() および
array_merge_recursive()
関数は、引数なしでも呼び出せるようになりました。この場合、空の配列が返されます。これは、array_merge(...$arrays)
のように、... 演算子と組み合わせて使う時に便利です。
proc_open() 関数
proc_open() 関数は、コマンドの文字列ではなく、配列を受け入れるようになりました。この場合、プロセスは(shellを通さず) 直接オープンされ、PHP が必要な引数のエスケープをすべて行います。
<?php
proc_open(['php', '-r', 'echo "Hello World\n";'], $descriptors, $pipes);
?>
proc_open() が、
redirect
と null
ディスクリプタをサポートしました。
<?php
// シェルにおける 2>&1 のような操作
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['redirect', 1]], $pipes);
// シェルにおける 2>/dev/null や 2>null のような操作
proc_open($cmd, [1 => ['pipe', 'w'], 2 => ['null']], $pipes);
?>
libargon なしでの argon2i(d)
PHP が libargon を使わずにビルドされた場合、password_hash() 関数は sodium 拡張モジュールの argon2i と argon2id を使った実装を使うようになります。
User Contributed Notes 2 notes
It should be noted that typed properties internally are never initialized to a default null. Unless of course you initialize them to null yourself. That's why you will always going to encounter this error if you try to access them before initialization.
**Typed property foo::$bar must not be accessed before initialization**
<?php
class User
{
public $id;
public string $name; // Typed property (Uninitialized)
public ?string $age = null; // Typed property (Initialized)
}
$user = new User;
var_dump(is_null($user->id)); // bool(true)
var_dump(is_null($user->name)); // PHP Fatal error: Typed property User::$name must not be accessed before initialization
var_dump(is_null($user->age));// bool(true)
?>
Another thing worth noting is that it's not possible to initialize a property of type object to anything other than null. Since the evaluation of properties happens at compile-time and object instantiation happens at runtime. One last thing, callable type is not supported due to its context-dependent behavior.
<?php
// How to get property type? For example for testing:
class Foo
{
private int $num;
private bool $isPositive;
private $notes;
}
$reflection = new \ReflectionClass(Foo::class);
$classProperties = $reflection->getProperties(\ReflectionProperty::IS_PRIVATE);
foreach ($classProperties as $classProperty) {
var_dump((string) $classProperty->getType());
}
/**
* Result:
* "int"
* "bool"
* ""
*/