PHP 8.4.1 Released!

新機能

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_rangemax_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_CAPTUREPREG_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;
?>
新しいシリアル化の機構は、 Serializable インターフェイス を置き換えるものです。 Serializable インターフェイスは将来非推奨になるでしょう。

引数を渡さずに 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() が、 redirectnull ディスクリプタをサポートしました。

<?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 を使った実装を使うようになります。

add a note

User Contributed Notes 2 notes

up
98
Rain
4 years ago
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.
up
7
wow-apps.pro
4 years ago
<?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"
* ""
*/
To Top