PHP 8.2の主な新機能
PHP 8.2は2022年12月にリリースされ、型システムの強化と読みやすいコードのための機能が中心です。弊社ではPHP 8.2を本番環境の標準バージョンとして採用しており、本記事ではよく使う機能を実践的に解説します。
readonlyプロパティ(8.1から拡張)
PHP 8.1でreadonly プロパティが導入され、8.2ではreadonly クラス全体に適用できるようになりました。
// PHP 8.2:クラス全体をreadonlyに
readonly class Money
{
public function __construct(
public readonly int $amount,
public readonly string $currency,
) {}
// readonlyクラス内のメソッドはOK
public function add(Money $other): static
{
if ($this->currency !== $other->currency) {
throw new \InvalidArgumentException('通貨が異なります');
}
return new static($this->amount + $other->amount, $this->currency);
}
public function format(): string
{
return match($this->currency) {
'JPY' => "¥{$this->amount}",
'USD' => "\${$this->amount}",
default => "{$this->amount} {$this->currency}",
};
}
}
// 使い方
$price = new Money(5000, 'JPY');
$tax = new Money(500, 'JPY');
$total = $price->add($tax);
echo $total->format(); // ¥5500
// 変更しようとするとエラー
$price->amount = 9999; // Error: Cannot modify readonly property
Enum型(PHP 8.1から)——実践的な使い方
Enumは定数の集合を型安全に表現できます。弊社では注文ステータス・ユーザーロール・支払い方法などに積極活用しています。
// Backed Enum(値あり)
enum OrderStatus: string
{
case Pending = 'pending';
case Confirmed = 'confirmed';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
// ラベル(日本語表示用)
public function label(): string
{
return match($this) {
self::Pending => '保留中',
self::Confirmed => '確定',
self::Shipped => '発送済',
self::Delivered => '配達完了',
self::Cancelled => 'キャンセル',
};
}
// 次に遷移可能なステータス
public function allowedTransitions(): array
{
return match($this) {
self::Pending => [self::Confirmed, self::Cancelled],
self::Confirmed => [self::Shipped, self::Cancelled],
self::Shipped => [self::Delivered],
default => [],
};
}
public function canTransitionTo(self $next): bool
{
return in_array($next, $this->allowedTransitions());
}
}
// Enumをモデルに適用
class Order extends Model
{
protected $casts = [
'status' => OrderStatus::class,
];
public function confirm(): void
{
if (!$this->status->canTransitionTo(OrderStatus::Confirmed)) {
throw new \LogicException(
"ステータス「{$this->status->label()}」から確定に遷移できません"
);
}
$this->update(['status' => OrderStatus::Confirmed]);
}
}
// 使い方
$order = Order::find(1);
echo $order->status->label(); // "保留中"
$order->confirm(); // OK
$order->confirm(); // LogicException: ステータス「確定」から確定に遷移できません
Enumのバリデーション
// LaravelのFormRequestでEnum値のバリデーション
use Illuminate\Validation\Rule;
public function rules(): array
{
return [
'status' => ['required', Rule::enum(OrderStatus::class)],
];
}
// Enumから値一覧を取得
$validValues = array_column(OrderStatus::cases(), 'value');
// ['pending', 'confirmed', 'shipped', 'delivered', 'cancelled']
DNF型(Disjunctive Normal Form)
PHP 8.2でIntersection型とUnion型を組み合わせたDNF型が使えるようになりました。
// (AかつB) または (CかつD) という複合型
function processInput(
(Countable&Iterator)|null $input
): void {
if ($input === null) {
return;
}
// $input は Countable かつ Iterator が保証される
echo count($input);
foreach ($input as $item) {
// ...
}
}
fibers(PHP 8.1から)——非同期処理の基礎
Fibersはコルーチンの仕組みで、処理を中断・再開できます。
$fiber = new Fiber(function(): void {
$value = Fiber::suspend('最初の値');
echo "再開時に受け取った値: {$value}\n";
Fiber::suspend('2番目の値');
});
$val1 = $fiber->start();
echo "中断: {$val1}\n"; // "中断: 最初の値"
$val2 = $fiber->resume('こんにちは');
echo "再中断: {$val2}\n";
// "再開時に受け取った値: こんにちは"
// "再中断: 2番目の値"
非推奨機能——PHP 8.2で削除
| 機能 | 移行先 |
|---|---|
${var} 文字列補間 |
{$var} |
| 動的プロパティ | 明示的にプロパティを宣言する |
utf8_encode() / utf8_decode() |
mb_convert_encoding() |
FILTER_SANITIZE_STRING |
htmlspecialchars() など |
// NG:PHP 8.2で非推奨の動的プロパティ
class User
{
// $nameプロパティが未定義のまま使用
}
$user = new User();
$user->name = '山田'; // Deprecated警告
// OK:プロパティを宣言する
class User
{
public string $name = '';
}
まとめ
PHP 8.2のreadonlyクラスとEnum型は、コードの不変性と型安全性を高め、バグを未然に防ぐ強力な機能です。弊社ではLaravelプロジェクトでこれらを積極的に活用し、保守性の高いシステムを構築しています。
PHP/Laravelによるシステム開発のご相談はお気軽にどうぞ。