Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】T_NULLSAFE_OBJECT_OPERATOR定数の使い方

T_NULLSAFE_OBJECT_OPERATOR定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

T_NULLSAFE_OBJECT_OPERATOR定数は、PHP 8で新たに導入されたnull安全演算子(?->)を表すトークンIDの定数です。この定数自体は、PHPのソースコードを解析するパーサや、静的解析ツールなどが、コード中に現れる?->という記号を識別し、処理するために内部的に使用されます。

null安全演算子(?->)は、オブジェクトのプロパティやメソッドにアクセスする際に、そのオブジェクトがnullであるかどうかを自動的にチェックし、安全に処理を進めるための画期的な機能です。これまでのPHPでは、オブジェクトがnullであるにもかかわらず、そのプロパティやメソッドにアクセスしようとすると、TypeErrorというエラーが発生し、プログラムが停止してしまうことがありました。この問題を回避するためには、if ($object !== null) { $object->method(); } のように、常に明示的なnullチェックを行う必要があり、コードが冗長になる傾向がありました。

このnull安全演算子を使用すると、例えば $object?->property$object?->method() のように簡潔に記述できます。もし $objectnullではない場合は通常通りプロパティへのアクセスやメソッドの実行が行われますが、もし $objectnullである場合は、それ以上アクセスを試みることなく、式全体の結果としてnullが返されます。これにより、エラーの発生を防ぎながら、条件分岐のコードを大幅に削減し、コードの記述量を減らして可読性を向上させることが可能になります。

T_NULLSAFE_OBJECT_OPERATOR定数は、このような堅牢で簡潔なコード記述を可能にするnull安全演算子の存在をPHPの内部システムに伝え、PHP 8における現代的な開発を支える基盤の一部となっています。

構文(syntax)

1$nullableObject?->propertyName;

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP8 Nullsafe Operatorで安全にアクセスする

1<?php
2
3/**
4 * 住所情報を表すクラスです。
5 * オブジェクト指向プログラミングの基本的なデータ構造として使用します。
6 */
7class Address
8{
9    public string $street;
10    public string $city;
11
12    public function __construct(string $street, string $city)
13    {
14        $this->street = $street;
15        $this->city = $city;
16    }
17
18    /**
19     * 完全な住所を文字列として返します。
20     */
21    public function getFullAddress(): string
22    {
23        return $this->street . ', ' . $this->city;
24    }
25}
26
27/**
28 * ユーザー情報を表すクラスです。
29 * 住所オブジェクトを持つことができ、住所が設定されていない場合はnullになります。
30 */
31class User
32{
33    public string $name;
34    // ?Address は、このプロパティが Address オブジェクトか、または null であることを示します。
35    public ?Address $address;
36
37    public function __construct(string $name, ?Address $address = null)
38    {
39        $this->name = $name;
40        $this->address = $address;
41    }
42
43    /**
44     * ユーザーの住所オブジェクトを返します。
45     * 住所が設定されていない場合は null を返します。
46     */
47    public function getAddress(): ?Address
48    {
49        return $this->address;
50    }
51
52    /**
53     * ユーザーの名前を返します。
54     */
55    public function getName(): string
56    {
57        return $this->name;
58    }
59}
60
61/**
62 * PHP 8 で導入された Null Safe Operator (?->) の使用例を示す関数です。
63 * このオペレータは、オブジェクトが null である可能性のある場合に、
64 * そのプロパティやメソッドに安全にアクセスするために使用されます。
65 * null のオブジェクトにアクセスしようとすると、従来はエラー(TypeError)が発生しましたが、
66 * Null Safe Operator を使用すると、エラーにならずに null が返されます。
67 */
68function demonstrateNullSafeOperator(): void
69{
70    echo "--- Null Safe Operator (?->) のデモンストレーション ---" . PHP_EOL;
71
72    // シナリオ1: 住所を持つユーザーの場合
73    $address1 = new Address('123 Main St', 'Anytown');
74    $userWithAddress = new User('Alice', $address1);
75
76    echo "■ 住所が設定されているユーザー (" . $userWithAddress->getName() . ") の場合:" . PHP_EOL;
77
78    // userWithAddress->getAddress() は Address オブジェクトを返します。
79    // そのため、?-> の後に続く city プロパティにアクセスできます。
80    $city1 = $userWithAddress->getAddress()?->city;
81    // null合体演算子 (??) を使用して、結果が null の場合にデフォルト値を設定しています。
82    echo "  居住都市: " . ($city1 ?? '不明') . PHP_EOL; // 出力: Anytown
83
84    // 同様に、メソッド呼び出しにも Null Safe Operator を適用できます。
85    $fullAddress1 = $userWithAddress->getAddress()?->getFullAddress();
86    echo "  完全な住所: " . ($fullAddress1 ?? '住所なし') . PHP_EOL; // 出力: 123 Main St, Anytown
87
88    echo PHP_EOL;
89
90    // シナリオ2: 住所を持たないユーザーの場合
91    $userWithoutAddress = new User('Bob'); // address プロパティはデフォルトで null です。
92
93    echo "■ 住所が設定されていないユーザー (" . $userWithoutAddress->getName() . ") の場合:" . PHP_EOL;
94
95    // userWithoutAddress->getAddress() は null を返します。
96    // Null Safe Operator (?->) が使われているため、その後の city プロパティへの
97    // アクセスはスキップされ、式全体の評価結果は null になります。
98    $city2 = $userWithoutAddress->getAddress()?->city;
99    echo "  居住都市: " . ($city2 ?? '不明') . PHP_EOL; // 出力: 不明
100
101    // メソッド呼び出しの場合も同様に、null が返されます。
102    $fullAddress2 = $userWithoutAddress->getAddress()?->getFullAddress();
103    echo "  完全な住所: " . ($fullAddress2 ?? '住所なし') . PHP_EOL; // 出力: 住所なし
104
105    echo PHP_EOL;
106
107    // 参考: Null Safe Operator がない場合のコードとの比較
108    echo "--- 従来の null チェックと比較 (Bob の場合) ---" . PHP_EOL;
109    $cityTraditional = '不明';
110    $addressObj = $userWithoutAddress->getAddress(); // まずgetAddressの結果を変数に格納
111    if ($addressObj !== null) {
112        // null でないことを確認してからプロパティにアクセス
113        $cityTraditional = $addressObj->city;
114    }
115    echo "  居住都市 (従来のチェック): " . $cityTraditional . PHP_EOL;
116    echo "  Null Safe Operator は、このように冗長になりがちな null チェックを簡潔に記述できる利点があります。" . PHP_EOL;
117}
118
119// Null Safe Operator のデモンストレーション関数を実行します。
120demonstrateNullSafeOperator();
121
122?>

このサンプルコードは、PHP 8で導入されたNull Safe Operator (?->) の使用方法を説明しています。この演算子は、nullの可能性があるオブジェクトのプロパティやメソッドに安全にアクセスするために活用されます。

従来のPHPでは、nullのオブジェクトにアクセスするとエラーが発生しました。しかし、Null Safe Operatorを使用すると、左側の式がnullと評価された場合、その後のアクセスはスキップされ、式全体の評価結果がnullとなります。これにより、冗長なnullチェックを省略し、コードを簡潔に記述できます。

例えば、住所情報を持たないユーザーのケースでは、getAddress()メソッドがnullを返します。このnullに対して?->cityのようにアクセスしてもエラーは発生せず、nullが返されます。一方、住所を持つユーザーの場合は、期待通りにプロパティやメソッドにアクセスし、値を取得できます。サンプルコードでは、この?->null合体演算子 (??) を組み合わせることで、nullの場合にデフォルト値を設定する、より実用的な方法も示されており、堅牢性と可読性を向上させます。

このサンプルコードで示されるNull Safe Operator (?->) は、PHP 8で導入された重要な機能です。オブジェクトがnullである可能性のある状況で、プロパティやメソッドに安全にアクセスできるようになります。この演算子の左側にある式がnullと評価された場合、その後のプロパティアクセスやメソッド呼び出しは実行されず、式全体の結果はnullとなります。これにより、従来発生していたTypeErrorを防ぎ、コードをより簡潔に記述できます。ただし、結果がnullになる可能性があるため、その後の処理でnullを想定していないと予期せぬエラーにつながることがあります。そのため、Null Safe Operatorの後にnull合体演算子 (??) を用いてデフォルト値を設定するなど、nullの可能性を適切にハンドリングすることが、安全で堅牢なコードを書く上で非常に重要です。

PHP 8 Null Safe Operator で安全にプロパティアクセスする

1<?php
2
3/**
4 * 住所を表すクラス。
5 */
6class Address
7{
8    public ?string $street;
9
10    public function __construct(?string $street = null)
11    {
12        $this->street = $street;
13    }
14}
15
16/**
17 * 人を表すクラス。住所を持つ可能性がある。
18 */
19class Person
20{
21    public ?Address $address;
22
23    public function __construct(?Address $address = null)
24    {
25        $this->address = $address;
26    }
27}
28
29/**
30 * PHP 8 で導入された Null Safe Operator (?->) の使用例を示します。
31 * オブジェクトが null の可能性がある場合のプロパティアクセスを簡潔にします。
32 */
33function demonstrateNullSafeOperator(): void
34{
35    // ケース1: 全てのオブジェクトが存在する場合
36    $personWithAddress = new Person(new Address("123 Main St"));
37
38    // 旧来の null チェックを用いたプロパティアクセス
39    $streetLegacy1 = null;
40    if ($personWithAddress !== null && $personWithAddress->address !== null) {
41        $streetLegacy1 = $personWithAddress->address->street;
42    }
43    echo "ケース1 (全て存在) - 旧来: " . ($streetLegacy1 ?? 'N/A') . "\n";
44
45    // Null Safe Operator (?->) を用いたプロパティアクセス
46    // チェーン途中で null があれば、全体の評価結果は null となります。
47    $streetNullSafe1 = $personWithAddress?->address?->street;
48    echo "ケース1 (全て存在) - Null Safe: " . ($streetNullSafe1 ?? 'N/A') . "\n\n";
49
50
51    // ケース2: 途中のオブジェクト (Address) が null の場合
52    $personWithoutAddress = new Person(); // address プロパティが null
53
54    // 旧来の null チェックを用いたプロパティアクセス
55    $streetLegacy2 = null;
56    if ($personWithoutAddress !== null && $personWithoutAddress->address !== null) {
57        $streetLegacy2 = $personWithoutAddress->address->street;
58    }
59    echo "ケース2 (Addressがnull) - 旧来: " . ($streetLegacy2 ?? 'N/A') . "\n";
60
61    // Null Safe Operator (?->) を用いたプロパティアクセス
62    // $personWithoutAddress->address が null のため、ここで評価が停止し、
63    // $streetNullSafe2 には null が代入されます。
64    $streetNullSafe2 = $personWithoutAddress?->address?->street;
65    echo "ケース2 (Addressがnull) - Null Safe: " . ($streetNullSafe2 ?? 'N/A') . "\n\n";
66
67
68    // ケース3: 最初のオブジェクト (Person) 自体が null の場合
69    $nullPerson = null;
70
71    // 旧来の null チェックを用いたプロパティアクセス
72    $streetLegacy3 = null;
73    if ($nullPerson !== null && $nullPerson->address !== null) {
74        $streetLegacy3 = $nullPerson->address->street;
75    }
76    echo "ケース3 (Personがnull) - 旧来: " . ($streetLegacy3 ?? 'N/A') . "\n";
77
78    // Null Safe Operator (?->) を用いたプロパティアクセス
79    // $nullPerson が null のため、ここで評価が停止し、
80    // $streetNullSafe3 には null が代入されます。
81    $streetNullSafe3 = $nullPerson?->address?->street;
82    echo "ケース3 (Personがnull) - Null Safe: " . ($streetNullSafe3 ?? 'N/A') . "\n";
83}
84
85// 関数を実行して動作を確認
86demonstrateNullSafeOperator();

PHP 8で導入されたT_NULLSAFE_OBJECT_OPERATORは、?->というNull Safe Operatorとして利用され、オブジェクトがnullの可能性があるプロパティやメソッドへのアクセスを、エラーなく簡潔に行う機能です。

従来の多段階プロパティアクセスでは、$person->address->streetのように記述した場合、途中のオブジェクトがnullだとエラーが発生していました。これを防ぐためには、if文による冗長なnullチェックを各段階で行う必要があり、コードが複雑になりがちでした。

?->演算子を用いると、$person?->address?->streetのように記述できます。このチェーンの途中でオブジェクトがnullだった場合、それ以降のアクセスは行われず、式全体の結果としてnullが返されます。これにより、エラーを起こさずに安全に値を扱えるようになります。

サンプルコードでは、住所を持つPersonクラスの例で、全てのオブジェクトが存在するケース、途中のAddressnullのケース、そして最初のPerson自体がnullのケースの3パターンを、従来のnullチェックと比較しています。?->を用いることで、コードが簡潔になり、期待通りnullを返して安全に処理できることを確認できます。この機能はコードの可読性と堅牢性を大幅に向上させます。

PHP 8以降で導入されたNull Safe Operator (?->) は、オブジェクトチェーンの途中にnullが存在する可能性のあるプロパティやメソッドへのアクセスを簡潔にします。この演算子を用いると、もし途中のオブジェクトがnullであった場合でも、致命的なエラー(TypeError)になることなく、評価が停止して全体の戻り値がnullとなります。これにより、冗長なif文によるnullチェックを減らし、コードの可読性を向上させることができます。ただし、必ずPHP 8以上の環境で利用し、結果がnullになる可能性があるため、必要に応じてnull合体演算子 (??) などでデフォルト値を設定することを検討してください。

関連コンテンツ

関連プログラミング言語