PHP8から登場した新機能を試して、良かったものまとめるシリーズ。
今回は、以下。
- Null 合体演算子
- null safe 演算子
目次
実コードで比較
PHP8以前以後のコードで書き味を比較してみます。
Null 合体演算子
公式:https://www.php.net/manual/ja/migration70.new-features.php
<?php
// こんな果物屋さんがあって
$fruits = [
'lemon' => '100yen',
'orange' => '150yen',
];
// apple > lemon の優先順位で購入する場合
/**
* ~PHP8
* isset等、配列の添字の存在をチェックしてからアクセスしないと「Warning: Undefined array key 'apple'」になるので、このような冗長な書き方が必要
*/
$fruitsToBuy = isset($fruits['apple']) ? isset($fruits['apple']) : $fruits['lemon'];
/**
* PHP8~
* ??(null合体演算子)なら、以下の動きになる
* nullの左辺が非nullであれば、左辺を返す
* nullの左辺がnullであれば、右辺を返す
*/
$fruitsToBuy = $fruits['apple'] ?? $fruits['lemon'];
// ちなみに、??を連結して書くことも可能
$fruitsToBuy = $fruits['apple'] ?? $fruits['pineapple'] ?? $fruits['lemon'];
null safe 演算子
公式:https://www.php.net/manual/ja/language.oop5.basic.php#language.oop5.basic.nullsafe
<?php
/**
* Userクラスを以下仕様で定義
* name:名前がrequire
* sex:性別はoption. 使う場合、SEXクラスのインスタンスを設定する
*/
class User
{
public function __construct(
public string $name,
public ?SEX $sex = null
)
{
}
}
/**
* SEX(性別)クラスを以下仕様で定義
* 取り得る値は「1:男性」「2:女性」の2パターン
*/
class Sex
{
public const MAN = '1';
public const WOMAN = '2';
public function __construct(
public string $sex
)
{
if (!in_array($sex, [self::MAN, self::WOMAN])) {
throw new Exception('不正な値');
}
}
/**
* 男性かどうか判定
* @return bool
*/
public function isMan(): bool
{
return $this->sex === self::MAN;
}
}
// とあるUserインスタンスのSEXプロパティを参照して、性別を判定するケースを考える
// nameだけを設定した上で、Userインスタンスを生成した場合
$user = new User(name: 'hanako');
// SEXプロパティ自体が存在しないので「isMan」にアクセスすると「Fatal error: Uncaught Error: Call to a member function isMan() on null in ***」のエラーになる
echo ($user->sex->isMan());
// 上記のようなケースを回避するための書き方について、PHP8前後での違いを比較
/**
* ~PHP8
* Userインスタンスがsexプロパティを持っているかの判定を挟む必要がある分、冗長
*/
if ($user->sex !== null && $user->sex->isMan()) {
echo 'The user is a man';
} else {
echo 'The gender of the user cannot be determined';
}
/**
* PHP8~(null safe 演算子)
* 「user->sex?」以降が実行されず「$user->sex?->isMan()」自体がnullを返すため、elseの分岐に入る
* 大分簡略化可能
*/
if ($user->sex?->isMan()) {
echo 'The user is man';
}
else {
echo 'The gender of the user cannot be determined';
}
/**
* null safeは連結可能(?->で左辺がnullとなる時点で、評価式全体としてnullを返すため)
* そのため、以下のような階層が深いオブジェクト等にアクセスする際により効果的
*/
$user?->getProfile()?->getAddress()?->getCity();
大分冗長な説明になってしまった…
まとめ
PHP8は良い書き味で、実業務でも多くの恩恵受けています。
引き続き他の機能もまとめておきたい。
コメント